32位汇编第三讲----【RedASM与代码注入】(2016-12-16)

0x00 关于函数入口点的指定

#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)
{
      // ...
}


  • mainCRTStartup的作用

作用:

它在执行一些初始化操作,如获取命令行参数、获取环境变量值、初始化全局变量、初始化io的所需各项准备之后,调用main(argc,argv)。main函数返回后,mainCRTStartup还需要调用全局变量的析构函数或者atexit()所登记的一些函数

0x02 代码注入与重定位

  • 为什么要先进行重定位

对于注入的代码,注入的地址与原本的地址不同

  • 如何重定位

当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

你可能感兴趣的:(科锐第三阶段笔记,汇编)