如何找到入口点
怎么寻找入口点Main函数受到不同因素影响 位置不一样发行版本 或者debug x86 x64 编译器版本都有可能影响main 函数位置纯真(老)版本 入口点[*]push
[*]push
[*]
[*]push
[*]call
入口点位置 fastcall 约定(在以前记录里能找到)RCXRDX R8入口点
怎么找main 函数 使用的实验代码我使用vs2015 版本的 代码 (MTD) 进行逆向#include <stdio.h>
#include <stdlib.h>
int main() {
printf("hello,world");
system("pause");
return 0;
}
此代码拖入 ida 进行分析 直接进入main函数 (有).plb直接进入main_0界面 ; Attributes: thunk
; int __cdecl main_0(int argc, const char **argv, const char **envp)
_main_0 proc near
argc= dword ptr4
argv= dword ptr8
envp= dword ptr0Ch
jmp _main
_main_0 endpjmp main 解释跳转到main 函数的地方 双击就可以非可视化界面 使用ctrl + "+"找到main 双击进入即可进入 主函数
__cdecl main_0但是 我们目的是什么 我们要探索该代码的规则 所以查看调用的 函数也就是__cdecl main_0使用交叉引用就可以 找到调用到上个 函数 快捷键位ctrl + x__cdecl invoke_main(); Attributes: library function bp-based frame
; int __cdecl invoke_main()
invoke_main proc near
push ebp
mov ebp, esp
call j___get_initial_narrow_environment
push eax ; envp
call j____p___argv
mov eax,
push eax ; argv
call j____p___argc
mov ecx,
push ecx ; argc
call _main_0 ;<---- 这个就是上个main_0 函数
add esp, 0Ch
pop ebp
retn
invoke_main endp
一共三个 call 第三个 call就是mian _0 我在注释上写 了 但是咱们不是往深处找 往 回找 找到最初的路线 cdecl invoke_mai 就是咱们要找的 点击进去然后 继续使用交叉引用跳转到invoke main 这里 就是刚才的入口 然后发现太麻烦了 可以选择变成普通模式空格键可以变普通模式FTP & _scrt_common_main_seh函数 add esp, 4
.text:00450EE6 movzx eax, al
.text:00450EE9 test eax, eax
.text:00450EEB jz short loc_450EFB
.text:00450EED mov ecx,
.text:00450EF0 mov edx,
.text:00450EF2 push edx ; _Callback
.text:00450EF3 call j___register_thread_local_exe_atexit_callback
.text:00450EF8 add esp, 4
.text:00450EFB
.text:00450EFB loc_450EFB: ; CODE XREF: __scrt_common_main_seh+128↑j
.text:00450EFB ; __scrt_common_main_seh+13B↑j
.text:00450EFB call invoke_main; main函数这里是个特殊的代码区 没有第二个 通过指令判断 这是什么 ? --> C++程序启动和线程局部存储(Thread Local Storage, TLS)向上翻找到特殊的关键字看到main 的时候__scrt_common_main__scrt_common_main_seh proc near ; CODE XREF: __scrt_common_main+8↑p
.text:00450DB0
.text:00450DB0 var_40 = dword ptr -40h
.text:00450DB0 var_3C = dword ptr -3Ch
.text:00450DB0 var_38 = dword ptr -38h
.text:00450DB0 return_code = dword ptr -34h
.text:00450DB0 xcptnum = dword ptr -30h
.text:00450DB0 main_result = dword ptr -2Ch
.text:00450DB0 Target = dword ptr -28h
.text:00450DB0 tls_dtor_callback= dword ptr -24h
.text:00450DB0 tls_init_callback= dword ptr -20h
.text:00450DB0 is_nested = byte ptr -1Ah
.text:00450DB0 has_cctor = byte ptr -19h
.text:00450DB0 ms_exc = CPPEH_RECORD ptr -18h
.text:00450DB0
.text:00450DB0 ; __unwind { // __except_handler4
.text:00450DB0 继续交叉引用 跳转到这里 这个函数 scrt_common_main()scrt_common_main proc near ; CODE XREF: _mainCRTStartup+3↓p
.text:00450D90 push ebp
.text:00450D91 mov ebp, esp
.text:00450D93 call j____security_init_cookie
.text:00450D98 call __scrt_common_main_seh;<--- 刚才那个函数上面那个的call 入口
.text:00450D9D pop ebp
.text:00450D9E retn
.text:00450D9E __scrt_common_main endp这个第二个call 就是 根据 scrt_common_main 反向推 继续交叉引用 你会寻找到唯一的call __scrt_common_main这就是刚才的入口继续找\mainCRTStartup()mainCRTStartup proc near ; CODE XREF: start_1↑j
.text:004510B0 push ebp
.text:004510B1 mov ebp, esp
.text:004510B3 call __scrt_common_main
.text:004510B8 pop ebp
.text:004510B9 retn
.text:004510B9 _mainCRTStartup endp这个是真正的入口点 vs 编译的入口点真正的入口点 mainCRTStartup然后继续往上推进 交叉引用 就会找到第一层 int __cdecl start_1().text:0044A730
.text:0044A730 ; int __cdecl start_1()
.text:0044A730 public start_1
.text:0044A730 start_1 proc near
.text:0044A730 jmp _mainCRTStartup
.text:0044A730 start_1 endp
.text:0044A730哎 你再交叉引用 你就没了这就是第一层了 没了我的历史写的 也许不太好但是可以借鉴一下
如果用ida的话,它加载完一个程序会自动跳到它判断的入口点,一般是main或WinMain,不知道它是不是这样判断的 Kuukyaku 发表于 2024-11-15 10:29
如果用ida的话,它加载完一个程序会自动跳到它判断的入口点,一般是main或WinMain,不知道它是不是这样判断 ...
这是如何手动寻找的原理 那个api是叫loadmodule 吧?有点印象得查一查 是的,还漏说了两
页:
[1]