32位汇编第三讲----【RedASM与代码注入】(2016-12-16)
来源:互联网 发布:iota 网络被攻击 编辑:程序博客网 时间:2024/06/06 03:03
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 0end_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 retInjectCode endp
0 0
- 32位汇编第三讲----【RedASM与代码注入】(2016-12-16)
- 32位汇编第三讲,RadAsm,IDE的配置和使用,以及汇编代码注入方式
- 32位汇编第三讲,RadAsm,IDE的配置和使用,以及汇编代码注入方式
- 16位汇编第七讲汇编指令详解第第三讲
- 16位汇编第十讲----8086指令集(6)【子程序与中断】
- 16位汇编第六讲汇编指令详解第二讲
- i386汇编中16位代码段与32位代码段的区别
- 16位汇编第五讲----8086指令集(1)
- 16位汇编第六讲----8086指令集(2)
- 16位汇编第七讲----8086指令集(3)
- 16位汇编第八讲----8086指令集(4)
- 16位汇编第五讲各种指令详解第一讲
- 16位汇编第八讲指令第四讲
- 32位汇编代码结构
- 汇编代码注入器
- 16位汇编第一讲----Debug的使用以及Hello World(2016.11.29)
- 16位汇编第二讲----8086的寄存器(2016.12.01)
- 16位汇编第八讲----8086指令集(5)【控制转移类指令】
- java android 时间类 DateTime extends java.util.GregorianCalendar
- Leetcode | Lowest Common Ancestor of a Binary Search Tree
- Implement strStr()
- 计算21世纪的闰年个数
- SAP Storage Location 从不参与MRP运算改成参与MRP运算的影响
- 32位汇编第三讲----【RedASM与代码注入】(2016-12-16)
- UINavigationBar,UITabBar背景图
- nat 协议
- Composer在ubuntu中的安装
- java枚举
- Android实现银行卡详情选择布局
- 编译时提示软件包javax.servlet.http不存在
- BufferedReader、BufferedWriter
- WebSocket + html 实现聊天室