Visual Studio 2017 获取真实导入符号地址
Get the real import symbol address on Visual Studio 2017
谁能解释一下为什么我无法从ngx_http_upstream_init
获取到对应的req->request_body->post_handler
地址,以及如何正确获取?
代码片段:
// Note: for debug test only
// https://reverseengineering.stackexchange.com/questions/14422/how-do-i-know-the-bytes-corresponding-to-an-instruction-in-hex-view-in-ida
logdf("%p, %p", ngx_http_upstream_init, req->request_body->post_handler);
ngx_http_upstream_init(req);
req->request_body->post_handler(req);
assert(ngx_http_upstream_init == req->request_body->post_handler);
// Skip post_handler because we don't want to create the upstream to the proxied server right now.
return NGX_HTTP_EM_HAS_SUBREQUEST(req) && 0 == req->request_body->rest ? NGX_AGAIN : NGX_OK;
日志:
ngx_http_request_body_filter_by_em|2681|00007FFACC961617, 00007FF727A8BA37
并且,在反汇编中 window,
;ngx_http_upstream_init(req);
00007FFACC9E66D1 48 8B 8D C0 01 00 00 mov rcx,qword ptr [req]
00007FFACC9E66D8 E8 3A AF F7 FF call ngx_http_upstream_init (07FFACC961617h)
;req->request_body->post_handler(req);
00007FFACC9E66DD 48 8B 85 C0 01 00 00 mov rax,qword ptr [req]
00007FFACC9E66E4 48 8B 80 90 03 00 00 mov rax,qword ptr [rax+390h]
00007FFACC9E66EB 48 8B 8D C0 01 00 00 mov rcx,qword ptr [req]
00007FFACC9E66F2 FF 50 40 call qword ptr [rax+40h]
但是,在即时 Window 中(对应于在 VS2017 中将鼠标光标悬停在工具提示鼠标上时):
ngx_http_upstream_init
0x00007ffacc9f6041 {ngx_http_em_module.dll!ngx_http_upstream_init}
req->request_body->post_handler
0x00007ff727a8ba37 {NGINX.exe!ngx_http_upstream_init}
我发现它的输出与前两种情况不同。
部分图片,
似乎我没有添加extern __declspec(dllimport)
来导入函数符号,所以编译器没有在导入table中添加存根条目,即.idata
segment/section和.text
中的一个跳转码segment/section,只是生成了多个跳转码。
这样添加后,
//
//
// https://docs.microsoft.com/en-us/cpp/cpp/definitions-and-declarations-cpp?view=msvc-160
// https://docs.microsoft.com/en-us/cpp/build/reference/exports?redirectedfrom=MSDN&view=msvc-160
// Note, in order to minimize modification, we use a .DEF file (one of four ways) to export a definition.
// grep --color -RP 'NGX_API (?!ngx_module)' /cygdrive/c/nginx --include=\*.{c,h}
// grep --color -R 'extern ' /cygdrive/c/nginx --include=\*.{c,h} -l | xargs sed -i 's/extern /NGX_API /g'
// grep --color -r 'NGX_API ngx_module_t' /cygdrive/c/nginx --include=\*.{c,h} -l | xargs sed -i 's/NGX_API ngx_module_t/extern ngx_module_t/g'
// NGX_API2: mainly used to distinguish between original extern symbols and those symbols we expect to export/import
#ifdef NGX_IMPORTS
#define NGX_API extern __declspec(dllimport)
#define NGX_API2 NGX_API
#else
#define NGX_API extern
#define NGX_API2
#endif
// nginx\src\http\ngx_http_upstream.h
NGX_API2 void ngx_http_upstream_init(ngx_http_request_t *r);
我得到了想要的结果。
ngx_http_request_body_filter_by_em|2681|00007FF7E89BBA37, 00007FF7E89BBA37
立即Window,
r9
140702736169527
ngx_http_upstream_init
0x00007ffacaf06840 {ngx_http_enforcer_module.dll!ngx_http_upstream_init}
req->request_body->post_handler
NGINX.exe!0x00007ff7e89bba37 (load symbols for additional information)
0x00007ff7e89bba37
140702736169527
谁能解释一下为什么我无法从ngx_http_upstream_init
获取到对应的req->request_body->post_handler
地址,以及如何正确获取?
代码片段:
// Note: for debug test only
// https://reverseengineering.stackexchange.com/questions/14422/how-do-i-know-the-bytes-corresponding-to-an-instruction-in-hex-view-in-ida
logdf("%p, %p", ngx_http_upstream_init, req->request_body->post_handler);
ngx_http_upstream_init(req);
req->request_body->post_handler(req);
assert(ngx_http_upstream_init == req->request_body->post_handler);
// Skip post_handler because we don't want to create the upstream to the proxied server right now.
return NGX_HTTP_EM_HAS_SUBREQUEST(req) && 0 == req->request_body->rest ? NGX_AGAIN : NGX_OK;
日志:
ngx_http_request_body_filter_by_em|2681|00007FFACC961617, 00007FF727A8BA37
并且,在反汇编中 window,
;ngx_http_upstream_init(req);
00007FFACC9E66D1 48 8B 8D C0 01 00 00 mov rcx,qword ptr [req]
00007FFACC9E66D8 E8 3A AF F7 FF call ngx_http_upstream_init (07FFACC961617h)
;req->request_body->post_handler(req);
00007FFACC9E66DD 48 8B 85 C0 01 00 00 mov rax,qword ptr [req]
00007FFACC9E66E4 48 8B 80 90 03 00 00 mov rax,qword ptr [rax+390h]
00007FFACC9E66EB 48 8B 8D C0 01 00 00 mov rcx,qword ptr [req]
00007FFACC9E66F2 FF 50 40 call qword ptr [rax+40h]
但是,在即时 Window 中(对应于在 VS2017 中将鼠标光标悬停在工具提示鼠标上时):
ngx_http_upstream_init
0x00007ffacc9f6041 {ngx_http_em_module.dll!ngx_http_upstream_init}
req->request_body->post_handler
0x00007ff727a8ba37 {NGINX.exe!ngx_http_upstream_init}
我发现它的输出与前两种情况不同。
部分图片,
似乎我没有添加extern __declspec(dllimport)
来导入函数符号,所以编译器没有在导入table中添加存根条目,即.idata
segment/section和.text
中的一个跳转码segment/section,只是生成了多个跳转码。
这样添加后,
//
//
// https://docs.microsoft.com/en-us/cpp/cpp/definitions-and-declarations-cpp?view=msvc-160
// https://docs.microsoft.com/en-us/cpp/build/reference/exports?redirectedfrom=MSDN&view=msvc-160
// Note, in order to minimize modification, we use a .DEF file (one of four ways) to export a definition.
// grep --color -RP 'NGX_API (?!ngx_module)' /cygdrive/c/nginx --include=\*.{c,h}
// grep --color -R 'extern ' /cygdrive/c/nginx --include=\*.{c,h} -l | xargs sed -i 's/extern /NGX_API /g'
// grep --color -r 'NGX_API ngx_module_t' /cygdrive/c/nginx --include=\*.{c,h} -l | xargs sed -i 's/NGX_API ngx_module_t/extern ngx_module_t/g'
// NGX_API2: mainly used to distinguish between original extern symbols and those symbols we expect to export/import
#ifdef NGX_IMPORTS
#define NGX_API extern __declspec(dllimport)
#define NGX_API2 NGX_API
#else
#define NGX_API extern
#define NGX_API2
#endif
// nginx\src\http\ngx_http_upstream.h
NGX_API2 void ngx_http_upstream_init(ngx_http_request_t *r);
我得到了想要的结果。
ngx_http_request_body_filter_by_em|2681|00007FF7E89BBA37, 00007FF7E89BBA37
立即Window,
r9
140702736169527
ngx_http_upstream_init
0x00007ffacaf06840 {ngx_http_enforcer_module.dll!ngx_http_upstream_init}
req->request_body->post_handler
NGINX.exe!0x00007ff7e89bba37 (load symbols for additional information)
0x00007ff7e89bba37
140702736169527