|
准备弃坑,放点毒出来。
测试了几款POST\GET的工具模块,发现有个通病:协议头处理方面,如果是大厂的一些APP,都会自定义协议头,而且去掉一些协议头,做自己的定制开发的http服务端,换句话来说,你们所认为的http欺骗应答,其实是你用的模块惹的祸。
关于HTTP的通讯,无非就是在TCP基础上的定义的一个通讯模式。我们现在用的几个主流模块:鱼刺、精易模块,看似非常人性化的处理了Cookies信息,让我们的访问更加容易的成功去通信,但是,精确度完全不够,比如:协议头。并不是所有的协议头都是完全的1:1还原,导致了在协议收发的产品上有各种各样的问题。 (当然我这里说的是一种比较极端的情况,如果你的应用需求没那么高,就是为了方面,我下面的话你就别看了,浪费时间)
1、鱼刺测试:可以关闭掉协议头的自定义添加和收发,通过抓包发现,可以实现。但是一个致命的点,不支持2.0,搞某X协议的人都知道,TX等大厂都加入了2.0的监测,导致了各种不能一比一还原;我可以负责任的告诉你,真正好的协议,是可以和真实应用一摸一样,没有任何区别,且无法监测;
2、精易 网页_访问_对象 巴拉下源码,就可以看出来,会添加一些协议头,而且关闭了也会带一点,放低点要求,就是你会发现,协议头的顺序有变化(别跟我说协议头顺序没有影响,至于你说没影响的,我只能呵呵,你自己写下服务端,看下数据顺序能不能分辨就行了,没有哪个大厂的服务器端没有定向开发过的);
3、Curl:官方文档支持各种调用,但是想用上完美的http/2,完全一比一还原数据包,包括顺序也不变,你需要引入ssl的一些dll来配合。之说到这些。当然你也可以用java等各种搞也能弄出来。
我以某Y做例子:app的收发组件有个很明显的工作逻辑:POST的请求,首先判断提交数据的长度,然后判断是否提交Cookies,然后判断其他的各种顺序,这个变化就可以演变。
反向的思考这件事:其实在做框架设计的时候,应该更多的考虑,你的框架在底层上面能不能做专有的检测接口,比如:http的POST请求和GET请求,能不能再利用专有修改的稳定性UDP来通信,实现现有的市场通路货抓包都变成不可能? 在提交通信方式上改变模式,增加自己的监测接口,让协议模拟变成光腚裸奔? 呵呵~
当然,你也许会说,某Y等厂采用通用通讯模块是为了兼容多端多方式的推广所需,那我想反问一句,基于CDN基础上的存储技术,实现多端的访问和服务器端相应的中间件调用跳转,他不香吗??
总归要放点干货,放一段源码上来。事先声明,不是全的,只能作为参考。我是小白,啥都不会。不喜勿喷。(半截代码,应该能看出来点啥了)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
// attach to process
// return FALSE to fail DLL load
break;
case DLL_PROCESS_DETACH:
// detach from process
break;
case DLL_THREAD_ATTACH:
// attach to thread
break;
case DLL_THREAD_DETACH:
// detach from thread
break;
}
return TRUE; // succesful
}
struct write_data
{
char *pc_ptr;
unsigned int ui_pos;
unsigned int ui_len;
};
static size_t xcurl_write_data(void *ptr, size_t size, size_t nmemb, void *userdata)
{
struct write_data *pst_write_data = (struct write_data *)userdata;
if ( ((char *)0 == pst_write_data->pc_ptr) )
{
return size * nmemb;
}
if ( pst_write_data->ui_pos + size * nmemb + 1 > pst_write_data->ui_len )
{
return 0;
}
memcpy( pst_write_data->pc_ptr + pst_write_data->ui_pos, ptr, size * nmemb);
pst_write_data->ui_pos += (size * nmemb);
pst_write_data->pc_ptr[ pst_write_data->ui_pos ] = 0x00;
return size * nmemb;
}
//http_ver 1.0 = 1, 1.1= 2, 2.0 = 3
//i_http_post 0:get other: post
/*extern "C"*/ DLL_EXPORT int xcurl( const char *pcc_url
, const char *pcc_header
, int i_http_ver
, int i_http_post
, const char *pcc_send_content
, unsigned int ui_send_content_len
, char *pc_recv_content
, unsigned int ui_recv_content_len
, char *pc_recv_header
, unsigned int ui_recv_header_len
, const char* pcc_proxy
, int i_proxy_type
)
{
int i_result = -1;
CURL *pst_curl = (CURL *)0;
struct curl_slist *pst_headers = (struct curl_slist *)0;
CURLcode res = 0;
struct write_data st_header_data = { 0 };
struct write_data st_content_data = { 0 };
curl_global_init(CURL_GLOBAL_DEFAULT);
for ( ; ; )
{
pst_curl = curl_easy_init();
if ( (CURL *)0 == pst_curl )
{
break;
}
if ( (const char*)0 != pcc_proxy )
{
curl_easy_setopt(pst_curl, CURLOPT_PROXY, pcc_proxy);
curl_easy_setopt(pst_curl, CURLOPT_PROXYTYPE, i_proxy_type);
}
curl_easy_setopt(pst_curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(pst_curl, CURLOPT_SSL_VERIFYHOST, 0L);
if ( ((const char *)0 != pcc_send_content) && ( 0 != ui_send_content_len) )
{
curl_easy_setopt(pst_curl, CURLOPT_POSTFIELDS, pcc_send_content);
curl_easy_setopt(pst_curl, CURLOPT_POSTFIELDSIZE, ui_send_content_len);
}
curl_easy_setopt( pst_curl, CURLOPT_HTTP_VERSION, i_http_ver );
curl_easy_setopt( pst_curl, CURLOPT_URL, pcc_url );
curl_easy_setopt( pst_curl, CURLOPT_POST, i_http_post);
curl_easy_setopt(pst_curl, CURLOPT_WRITEFUNCTION, xcurl_write_data);
st_header_data.pc_ptr = pc_recv_header;
st_header_data.ui_pos = 0;
st_header_data.ui_len = ui_recv_header_len;
st_content_data.pc_ptr = pc_recv_content;
st_content_data.ui_pos = 0;
st_content_data.ui_len = ui_recv_content_len;
curl_easy_setopt( pst_curl, CURLOPT_HEADERDATA, &st_header_data );
curl_easy_setopt( pst_curl, CURLOPT_WRITEDATA, &st_content_data );
if ( (char *)0 != pcc_header )
{
pst_headers = curl_slist_append(pst_headers, pcc_header);
|
|