#pragma comment( linker, "/subsystem:windows /entry:WinMainCRTStartup" )
#pragma comment( linker, "/subsystem:windows /entry:mainCRTStartup" )
#pragma comment( linker, "/subsystem:console /entry:mainCRTStartup" )
#pragma comment( linker, "/subsystem:console /entry:WinMainCRTStartup" )
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// ...
}
int main(void)
{
// ...
}
作用:
它在执行一些初始化操作,如获取命令行参数、获取环境变量值、初始化全局变量、初始化io的所需各项准备之后,调用main(argc,argv)。main函数返回后,mainCRTStartup还需要调用全局变量的析构函数或者atexit()所登记的一些函数
对于注入的代码,注入的地址与原本的地址不同
当CALL执行时,CPU首先把要返回的地址
(即下一条指令的地址)压入堆栈,然后跳到我们目的地址执行。可以看出,在跳转之后只要执行一条POP指令或MOV
EXX,[ESP]就可以得到下一条指令在内存中的实际位置了。其实,对于任何一个变量,我们都可以采用这种方式进行重定位
基本步骤如下:
(1)用CALL指令跳转到下一条指令,使z1在内存中的实际地址进栈。 (2)用POP xx 或MOV
EXX,[ESP]取出栈顶的内容,这样就得到了z1的地址 (BaSe)。 (3)其他指令
(变量、常量)的实际地址就等于Base+(0ffSetLabe1-OffSet vstart)。
实例代码:
//----------------------------
call vStart // call这个动作发生的时候,会把返回地址退入堆栈的顶部,此时返回地址就是vStart所在位置的绝对地址,当然call这个函数是通过相对偏移来调用的,不存在重定位的问题
vStart:
pop ebp //这里取出返回地址,注意此地址是进程空间里面的绝对地址
sub ebp,offset vStart //把绝对地址和相对偏移相减就可以获得相对偏移与绝对地址的转换关系
mov eax, [ebp+kernel32] ;//有了转换关系之后就可以轻松调用各个由相对地址指定的数据段或者函数
kernel32 dd ?
//-------------------------------
代码注入的32位汇编关键代码:
begin_label:
call $+5 ;重定位
FIXADDR:
pop ebp
sub ebp, FIXADDR
push MB_OK
lea eax, [ebp + offset g_szTitle]
push eax
lea eax, [ebp + offset g_szMsg]
push eax
push NULL
mov eax, [ebp + offset g_pfnMessageBox]
call eax
ret
g_szTitle db 'Title', 0
g_szMsg db 'Hello World', 0
g_pfnMessageBox DWORD 0
end_label:
InjectCode proc
LOCAL @hCalc:HWND
LOCAL @dwPid :dword
LOCAL @hProcess :HANDLE
LOCAL @lpBuff :PVOID
LOCAL @hUser:HANDLE
LOCAL @oldProtect:DWORD
LOCAL @lpMsgBox:PVOID
invoke LoadLibrary, addr g_szUser32
mov @hUser, eax
;check
.if eax == NULL
invoke MessageBox,NULL,offset g_szUser32,offset g_err,MB_OK
ret
.endif
invoke GetProcAddress, @hUser, addr g_szMsgBox
mov @lpMsgBox, eax
;check
.if eax == NULL
invoke MessageBox,NULL,offset g_szGetProcAddress,offset g_err,MB_OK
ret
.endif
;修改内存保护属性
invoke VirtualProtect, addr begin_label, end_label - begin_label, \
PAGE_EXECUTE_READWRITE, addr @oldProtect
;check
.if eax == NULL
invoke MessageBox,NULL,offset g_szVirtualProtect,offset g_err,MB_OK
ret
.endif
mov eax, @lpMsgBox
mov g_pfnMessageBox, eax
;修改完一次过后需要再吃修改最开始的状态
invoke VirtualProtect, addr begin_label, end_label - begin_label, \
@oldProtect, addr @oldProtect
;check
.if eax == NULL
invoke MessageBox,NULL,offset g_szVirtualProtect,offset g_err,MB_OK
ret
.endif
invoke FreeLibrary,@hUser
;check
.if eax == NULL
invoke MessageBox,NULL,offset g_szFreeLibrary,offset g_err,MB_OK
ret
.endif
invoke FindWindow,NULL, addr g_szCalc
mov @hCalc, eax
;check
.if eax == NULL
invoke MessageBox,NULL,offset g_szFindWindow,offset g_err,MB_OK
ret
.endif
invoke GetWindowThreadProcessId,@hCalc, addr @dwPid
;check
mov eax,@dwPid
.if eax == NULL
invoke MessageBox,NULL,offset g_szGetWindowThreadProcessId,offset g_err,MB_OK
ret
.endif
invoke OpenProcess, PROCESS_ALL_ACCESS, FALSE, @dwPid
mov @hProcess, eax
;check
.if eax == NULL
invoke MessageBox,NULL,offset g_szOpenProcess,offset g_err,MB_OK
ret
.endif
;申请内存
invoke VirtualAllocEx, @hProcess, NULL, 1000h, MEM_COMMIT, PAGE_EXECUTE_READWRITE
mov @lpBuff, eax
mov g_szAddr,eax
;check
.if eax == NULL
invoke MessageBox,NULL,offset g_szVirtualAllocEx,offset g_err,MB_OK
ret
.endif
;写入内存
invoke WriteProcessMemory,@hProcess, @lpBuff, \
addr begin_label, end_label - begin_label, NULL
;check
.if eax == 0
invoke MessageBox,NULL,offset g_szWriteProcessMemory,offset g_err,MB_OK
ret
.endif
;创建远程线程
invoke CreateRemoteThread,@hProcess, NULL, 0, @lpBuff, NULL, 0, NULL
;check
.if eax == NULL
invoke MessageBox,NULL,offset g_szCreateRemoteThread,offset g_err,MB_OK
ret
.endif
;释放内存
invoke VirtualFreeEx,@hProcess, @lpBuff, 1000h, MEM_RELEASE
;check
.if eax == 0
invoke MessageBox,NULL,offset g_szVirtualFreeEx,offset g_err,MB_OK
ret
.endif
ret
InjectCode endp