转眼一晃,注册看雪已经7个月了,首先要感谢看雪学院的所有大牛们,从你们身上我学到了好多好多知识。
我想模仿一个插件的全部功能,并自己完善它,这个插件用到了dirextX库,要反编译它,不是件容易的事,我今天就先反汇编了一下自己写的函数,先磨磨刀,等磨的差不多了就要实战了。
废话不多说了,上源码,特别感谢一下fzhaoqiang,这个源码是跟这位仁兄学的。
HRESULT CopyBmp(TCHAR* filename,IDirect3DDevice9* pDev)
{
HRESULT hr;
D3DDISPLAYMODE mode;
IDirect3DSurface9* surf;
if (FAILED(hr=pDev-> GetDisplayMode(0,&mode)))
return hr;
if (FAILED(hr=pDev->CreateOffscreenPlainSurface(mode.Width,mode.Height,D3DFMT_A8R8G8B8,D3DPOOL_SYSTEMMEM,&surf,NULL)))
return hr;
if (FAILED(hr=pDev->GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_FORCE_DWORD,&surf)))
{
surf-> Release();
return hr;
}
hr=D3DXSaveSurfaceToFile(filename,D3DXIFF_JPG,surf,NULL,NULL);
surf-> Release();
return hr;
}
IDA没有生成这个函数的流程图,所以也没发发出来了,可能是我还对IDA水平太差了。
以下是我对IDA反汇编代码的理解,请大家多多指教,我是新手,有错误的地方请大牛们别见笑。
.text:00412D50
.text:00412D50 loc_412D50: ; CODE XREF: .text:0041125Dj
.text:00412D50 push ebp ;保存原堆指针
.text:00412D51 mov ebp, esp ;ebp指向栈空间,
.text:00412D53 sub esp, 0F4h ;开辟栈空间
.text:00412D59 push ebx ;保存原栈顶
.text:00412D5A push esi ;保存esi
.text:00412D5B push edi ;保存edi
.text:00412D5C lea edi, [ebp-0F4h] ;edi指向栈顶 0xF4/0x4=61,61*4=124字节空间
.text:00412D62 mov ecx, 3Dh ;设置初始化局部变量循环的次数,0xF4/0x4正好等于3Dh,very good终于明白了
.text:00412D67 mov eax, 0CCCCCCCCh ;初始化前,eax就是0CCCCCCCCh,C++就是这样的
.text:00412D6C rep stosd ;初始化局部变量
.text:00412D6E mov eax, dword_42D180;取进程cookie,送入eax
.text:00412D73 xor eax, ebp ;计算cookie保存在eax中
.text:00412D75 mov [ebp-4], eax ;[ebp-4]保存cookie,函数返回前弹出,子程序执行完返回前,检查堆栈是否保持平衡
.text:00412D78 mov esi, esp ;esi指向栈顶
.text:00412D7A lea eax, [ebp-24h] ;[ebp-24h]为D3DDISPLAYMODE mode;结构体的指针
.text:00412D7D push eax ;压入IDirect3DSurface9结构体指针mode
.text:00412D7E push 0 ;iSwapChain=0,入栈
.text:00412D80 mov ecx, [ebp+0Ch]
.text:00412D83 mov edx, [ecx] ;edx保存返回值hr
.text:00412D85 mov eax, [ebp+0Ch]
.text:00412D88 push eax ;hr入栈
.text:00412D89 mov ecx, [edx+20h] ;[edx+20h]是IDirect3DDevice9::GetDisplayMode(UINT iSwapChain,D3DDISPLAYMODE *pMode)函数的指针
.text:00412D8C call ecx ;GetDisplayMode(0,&mode)
.text:00412D8E cmp esi, esp ;esi保存的是栈顶,而子函数调用中改变的是esp的值,所以比较esi和esp的值
.text:00412D90 call sub_41191F ;然后call __RTC_CheckEsp()检查堆栈是否平衡
.text:00412D95 mov [ebp-0Ch], eax ;返回hr,[ebp-0Ch]就是hr的地址
.text:00412D98 cmp dword ptr [ebp-0Ch], 0 ;判断hr是否大于等于0,大于等于0则成功
.text:00412D9C jge short loc_412DA6 ;GetDisplayMode(0,&mode)获取显示模式成功,则跳转到0x412DA6
.text:00412D9E mov eax, [ebp-0Ch] ;return hr;所以要eax要保存hr的值
.text:00412DA1 jmp loc_412E59 ;GetDisplayMode(0,&mode)获取显示模式失败,函数就返回,返回hr的值
.text:00412DA6 ; ---------------------------------------------------------------------------
.text:00412DA6
.text:00412DA6 loc_412DA6: ; CODE XREF: .text:00412D9Cj
.text:00412DA6 mov esi, esp ;esi指向栈顶
.text:00412DA8 push 0 ;HANDLE *pSharedHandle=NULL,获取的是屏幕的离屏表面
.text:00412DAA lea eax, [ebp-30h]
.text:00412DAD push eax ;IDirect3DSurface9 **ppSurface;
.text:00412DAE push 2 ;D3DPOOL Pool=D3DPOOL_SYSTEMMEM;
.text:00412DB0 push 15h ;D3DFORMAT Format=D3DFMT_A8R8G8B8;
.text:00412DB2 mov ecx, [ebp-20h]
.text:00412DB5 push ecx ;UINT Height=mode.Height;
.text:00412DB6 mov edx, [ebp-24h]
.text:00412DB9 push edx ;UINT Width=mode.Width;
.text:00412DBA mov eax, [ebp+0Ch]
.text:00412DBD mov ecx, [eax] ;ecx保存返回值hr
.text:00412DBF mov edx, [ebp+0Ch]
.text:00412DC2 push edx ;hr入栈
.text:00412DC3 mov eax, [ecx+90h] ;[ecx+90h]为IDirect3DDevice9::CreateOffscreenPlainSurface函数的指针
.text:00412DC9 call eax ;CALL CreateOffscreenPlainSurface
.text:00412DCB cmp esi, esp ;同上.text:00412D8E
.text:00412DCD call sub_41191F ;同上.text:00412D90,检查堆栈是否平衡
.text:00412DD2 mov [ebp-0Ch], eax ;返回hr
.text:00412DD5 cmp dword ptr [ebp-0Ch], 0 ;判断CreateOffscreenPlainSurface函数获取离屏表面是否成功
.text:00412DD9 jge short loc_412DE0 ;成功,则跳转到0x412DA6
.text:00412DDB mov eax, [ebp-0Ch] ;return hr;所以要eax要保存hr的值
.text:00412DDE jmp short loc_412E59 ;CreateOffscreenPlainSurface函数失败,函数就返回,返回hr的值
.text:00412DE0 ; ---------------------------------------------------------------------------
.text:00412DE0
.text:00412DE0 loc_412DE0: ; CODE XREF: .text:00412DD9j
.text:00412DE0 mov esi, esp ;esi指向栈顶
.text:00412DE2 lea eax, [ebp-30h] ;[ebp-30h]是IDirect3DSurface9指针surf的地址
.text:00412DE5 push eax ;IDirect3DSurface9 **ppBackBuffer=&surf;
.text:00412DE6 push 7FFFFFFFh ;D3DBACKBUFFER_TYPE Type=D3DBACKBUFFER_TYPE_FORCE_DWORD;
.text:00412DEB push 0 ;UINT BackBuffer=NULL;
.text:00412DED push 0 ;UINT iSwapChain=NULL;
.text:00412DEF mov ecx, [ebp+0Ch]
.text:00412DF2 mov edx, [ecx] ;ecx保存返回值hr
.text:00412DF4 mov eax, [ebp+0Ch]
.text:00412DF7 push eax ;返回值hr入栈
.text:00412DF8 mov ecx, [edx+48h] ;ecx保存[edx+48h]不知道是干什么的
.text:00412DFB call ecx ;call IDirect3DDevice9::GetBackBuffer获取后台图像数据
.text:00412DFD cmp esi, esp ;同上.text:00412D8E
.text:00412DFF call sub_41191F ;同上.text:00412D90,检查堆栈是否平衡
.text:00412E04 mov [ebp-0Ch], eax ;保存返回值hr
.text:00412E07 cmp dword ptr [ebp-0Ch], 0 ;判断GetBackBuffer函数获取离屏表面是否成功
.text:00412E0B jge short loc_412E29 ;GetBackBuffer函数失败,函数就返回,返回hr的值
.text:00412E0D mov eax, [ebp-30h] ;[ebp-30h]是IDirect3DSurface9指针surf的地址,从00412DE2行GetBackBuffer函数的最后参数判断出
.text:00412E10 mov ecx, [eax] ;ecx保存surf指针
.text:00412E12 mov esi, esp ;esi指向栈顶
.text:00412E14 mov edx, [ebp-30h] ;edx保存IDirect3DSurface9结构体指针surf
.text:00412E17 push edx ;IDirect3DSurface9结构体指针surf入栈
.text:00412E18 mov eax, [ecx+8] ;surf指针+8h为IDirect3DSurface9::Release()函数的指针
.text:00412E1B call eax ;CALL IDirect3DSurface9::Release();
.text:00412E1D cmp esi, esp ;同上.text:00412D8E
.text:00412E1F call sub_41191F ;同上.text:00412D90,检查堆栈是否平衡
.text:00412E24 mov eax, [ebp-0Ch] ;保存返回值hr
.text:00412E27 jmp short loc_412E59 ;Release()函数执行完,函数就返回
.text:00412E29 ; ---------------------------------------------------------------------------
.text:00412E29
.text:00412E29 loc_412E29: ; CODE XREF: .text:00412E0Bj
.text:00412E29 push 0 ;const RECT *pSrcRect=NULL;
.text:00412E2B push 0 ;const PALETTEENTRY *pSrcPalette=NULL;
.text:00412E2D mov eax, [ebp-30h]
.text:00412E30 push eax ;IDirect3DSurface9结构体指针surf
.text:00412E31 push 1 ;D3DXIMAGE_FILEFORMAT DestFormat=D3DXIFF_JPG;
.text:00412E33 mov ecx, [ebp+8]
.text:00412E36 push ecx ;LPCTSTR pDestFile这是要保存的图片绝对路径名
.text:00412E37 call j_D3DXSaveSurfaceToFileW ;这个函数ida直接识别出来了
.text:00412E3C mov [ebp-0Ch], eax ;保存返回值hr
.text:00412E3F mov eax, [ebp-30h]
.text:00412E42 mov ecx, [eax] ;ecx保存IDirect3DSurface9结构体指针surf
.text:00412E44 mov esi, esp ;esi指向栈顶
.text:00412E46 mov edx, [ebp-30h]
.text:00412E49 push edx ;IDirect3DSurface9结构体指针surf入栈
.text:00412E4A mov eax, [ecx+8]
.text:00412E4D call eax ;CALL IDirect3DSurface9::Release();
.text:00412E4F cmp esi, esp ;同上.text:00412D8E
.text:00412E51 call sub_41191F ;同上.text:00412D90,检查堆栈是否平衡
.text:00412E56 mov eax, [ebp-0Ch] ;保存返回值hr
.text:00412E59
.text:00412E59 loc_412E59: ; CODE XREF: .text:00412DA1j
.text:00412E59 ; .text:00412DDEj ...
.text:00412E59 push edx ;这里为什么要入栈保存edx,edx里应该是什么值还没想明白
.text:00412E5A mov ecx, ebp ;ecx保存栈顶指针
.text:00412E5C push eax ;保存函数返回值
.text:00412E5D lea edx, dword_412E88;再次取出进程cookie,送入eax
.text:00412E63 call sub_411401 ;CALL _RTC_CheckStackVars这个函数,从字面意思理解是检查堆参数,不明白还请大牛指点
.text:00412E68 pop eax ;恢复返回值hr到eax
.text:00412E69 pop edx ;恢复edx
.text:00412E6A pop edi ;恢复原edi
.text:00412E6B pop esi ;恢复原esi
.text:00412E6C pop ebx ;恢复原ebx
.text:00412E6D mov ecx, [ebp-4] ;对应00412D75行 弹出cookie到ecx,函数返回前弹出,子程序执行完返回前,检查堆栈是否保持平衡
.text:00412E70 xor ecx, ebp ;取进程cookie值,保存在ecx
.text:00412E72 call sub_411154 ;CALL __security_check_cookie函数检查堆栈是否保持平衡
.text:00412E77 add esp, 0F4h ;释放函数申请的栈空间
.text:00412E7D cmp ebp, esp ;同上.text:00412D8E
.text:00412E7F call sub_41191F ;同上.text:00412D90,检查堆栈是否平衡
.text:00412E84 mov esp, ebp ;恢复原esp
.text:00412E86 pop ebp ;恢复原ebx,ebx重新指向堆函数调用在堆中的位置
.text:00412E87 retn ;函数返回
.
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)