yC 逆着看
本帖最后由 whypro 于 2010-5-23 13:28 编辑yC 有源码但是我们逆着看
.386
.model flat, stdcall
option casemap:none
include \masm32\include\kernel32.inc ;<--------像c语言中的#include <stdio.h>
include \masm32\include\user32.inc
include \masm32\include\comdlg32.inc
include \masm32\include\shell32.inc
include \masm32\include\imagehlp.inc
includelib \masm32\lib\kernel32.lib ;<---------像c语言中的#pragma comment(lib,"Ws2_32.lib")
includelib \masm32\lib\user32.lib
includelib \masm32\lib\comdlg32.lib
includelib \masm32\lib\shell32.lib
includelib \masm32\lib\imagehlp.lib
include \masm32\include\windows.inc
include resource.inc
DlgProc PROTO :HWND, :UINT, :WPARAM, :LPARAM<---自定义函数,传说中的callback()函数
;------------ CONST --------- <---常量(#define PI 3.141)
.const
CHECK_SI_FLAG equ 1
ERASE_HEADER_FLAG equ 2
DESTROY_IMPORT_FLAG equ 4
CHECK_HEADER_CRC equ 8
ANTI_DUMP_FLAG equ 16
API_REDIRECT_FLAG equ 32
szFilter db "ExE files",0,"*.exe",0,"All files",0,"*.*",0,0
szCurDir db ".",0
szNoFile db "No file selected up to now !",0
szErr db "ERROR",0
;------------ DATA ---------- <------变量 (int a=0;)
.data
hInst dd 0
hDLG dd 0
ofn OPENFILENAME <>
cFname db MAX_PATH dup (0)
;------------ CODE ----------<------从这里开始运行!
.code
include CryptStuff.ASM
include PER.ASM
main:
invoke GetModuleHandle,0
mov hInst,eax
invoke DialogBoxParam,eax,IDD_MAINDLG,0,offset DlgProc,0
THEEND:
invoke ExitProcess,0
DlgProc proc hDlg:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCALhDrop : HANDLE
pushad
.IF uMsg == WM_INITDIALOG
invoke LoadIcon,hInst,IDI_ICON
invoke SendMessage,hDlg,WM_SETICON,TRUE,eax
push hDlg
pop hDLG
; check the checkboxes :)
invoke CheckDlgButton,hDlg,IDC_CHECKHEADERCRC,TRUE
invoke CheckDlgButton,hDlg,IDC_DESTROYIMPORT,TRUE
invoke CheckDlgButton,hDlg,IDC_ANTIDUMP,TRUE
INVOKE CheckDlgButton,hDlg,IDC_APIREDIRECT,TRUE
invoke DragAcceptFiles,hDlg,TRUE
.ELSEIF uMsg == WM_DROPFILES
push wParam
pop hDrop
invoke DragQueryFile,hDrop,0,offset cFname,sizeof cFname
invoke DragFinish,hDrop
invoke SetDlgItemText,hDlg,IDC_TARGETFILE,offset cFname
.ELSEIF uMsg == WM_COMMAND
mov eax,wParam
.IF ax == IDC_CLOSE
invoke SendMessage,hDlg,WM_CLOSE,NULL,NULL
.ELSEIF ax == IDC_CHOOSEFILE
; get a file path
mov ofn.lStructSize,SIZEOF ofn
mov ofn.lpstrFilter,offset szFilter
push hDlg
pop ofn.hwndOwner
mov ofn.lpstrFile, offset cFname
mov ofn.nMaxFile,SIZEOF cFname
mov ofn.lpstrInitialDir,offset szCurDir
mov ofn.Flags, OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or OFN_LONGNAMES or OFN_HIDEREADONLY
push offset ofn
call GetOpenFileName
test eax,eax
jz @@ExitDlgProc
invoke SetDlgItemText,hDlg,IDC_TARGETFILE,offset cFname
.ELSEIF ax == IDC_CRYPT
; ----- was a file selected ? -----
mov eax,offset cFname
.IF byte ptr == 0
invoke MessageBox,hDlg,offset szNoFile,offset szErr,MB_ICONERROR
jmp @@ExitDlgProc
.ENDIF
; ---- build the protection flag -----
xor edi,edi
invoke IsDlgButtonChecked,hDlg,IDC_SICHECK
.IF eax == BST_CHECKED
or edi,CHECK_SI_FLAG
.ENDIF
invoke IsDlgButtonChecked,hDlg,IDC_ERASEPEHEADER
.IF eax == BST_CHECKED
or edi,ERASE_HEADER_FLAG
.ENDIF
invoke IsDlgButtonChecked,hDlg,IDC_DESTROYIMPORT
.IF eax == BST_CHECKED
or edi,DESTROY_IMPORT_FLAG
.ENDIF
invoke IsDlgButtonChecked,hDlg,IDC_CHECKHEADERCRC
.IF eax == BST_CHECKED
or edi,CHECK_HEADER_CRC
.ENDIF
invoke IsDlgButtonChecked,hDlg,IDC_ANTIDUMP
.IF eax == BST_CHECKED
or edi,ANTI_DUMP_FLAG
.ENDIF
INVOKE IsDlgButtonChecked,hDlg,IDC_APIREDIRECT
.IF EAX == BST_CHECKED
OREDI, API_REDIRECT_FLAG
.ENDIF
push edi
push hDlg
push offset cFname
call CryptFile
.ENDIF
.ELSEIF uMsg == WM_CLOSE
invoke EndDialog,hDlg,0
.ENDIF
popad
@@ExitDlgProc:
xor eax,eax
ret
DlgProc endp
end main
[ 本帖最后由 whypro 于 2010-5-20 21:15 编辑 ] 本帖最后由 whypro 于 2010-5-22 15:14 编辑
004028EA >/$6A 00 push 0 ; /pModule = NULL
004028EC|.E8 6D020000 call <jmp.&KERNEL32.GetModuleHandleA> ; \GetModuleHandleA
004028F1|.A3 00104000 mov dword ptr ds:,eax
004028F6|.6A 00 push 0 ; /lParam = NULL
004028F8|.68 0E294000 push yC.0040290E ; |DlgProc = yC.0040290E
004028FD|.6A 00 push 0 ; |hOwner = NULL
004028FF|.6A 64 push 64 ; |pTemplate = 64
00402901|.50 push eax ; |hInst
00402902|.E8 8D020000 call <jmp.&USER32.DialogBoxParamA> ; \DialogBoxParamA
00402907|.6A 00 push 0 ; /ExitCode = 0
00402909\.E8 44020000 call <jmp.&KERNEL32.ExitProcess> ; \ExitProcess
有用的函数就这么几个,下面看我分析。
1.GetModuleHandleA
逆向时她穿的是0,而不是字符串!
所以接下来会得到eax=400000这个地址(挺熟悉的)。
当PE文件被加载到内存后,内存中的版本称为模块(Module),映射文件的起始地址称为模块句柄(hModule),可以通过模块句柄访问内存中的其他数据结构。这个初始内存地址也称为文件映像基址(ImageBase)。载入一个PE程序的主要步骤如下:
(1)当PE文件被执行时,PE装载器首先为进程分配一个4GB的虚拟地址空间,然后把程序所占用的磁盘空间作为虚拟内存映射到这个4GB的虚拟地址空间中。一般情况下,会映射到虚拟地址空间中0x400000的位置。装载一个应用程序的时间比一般人所设想的要少,因为装载一个PE文件并不是把这个文件一次性地从磁盘读到内存中,而是简单地做一个内存映射,映射一个大文件和映射一个小文件所花费的时间相差无几。当然,真正执行文件中的代码时,操作系统还是要把存在于磁盘上的虚拟内存中的代码交换到物理内存(RAM)中。但是,这种交换也不是把整个文件所占用的虚拟地址空间一次性地全部从磁盘交换到物理内存中,操作系统会根据需要和内存占用情况交换一页或多页。当然,这种交换是双向的,即存在于物理内存中的一部分当前没有被使用的页,也可能被交换到磁盘中。
(2)PE装载器在内核中创建进程对象和主线程对象以及其他内容。
(3)PE装载器搜索PE文件中的Import Table(引入表),装载应用程序所使用的动态链接库。对动态链接库的装载与对应用程序的装载方法完全类似。
(4)PE装载器执行PE文件首部所指定地址处的代码,开始执行应用程序主线程。
2.DialogBoxParamA
hInstance是当前应用程序的实例句柄。
lpTemplateName是对话框的资源模板。
hWndParent是父窗口的句柄。
lpDialogFunc是对话框的消息处理函数。
dwInitParam是初始化参数,这里缺省设置为0。
没什么好说的就是建立一个对话框。
lpDialogFunc是对话框的消息处理函数。(callback函数 DlgProc = yC.0040290E)
例子:DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_DIALOG), NULL, (DLGPROC)ProcMain, 0);
3.ExitProcess
例子:ExitProcess(0);
ExitProcess不负责,也不清理垃圾,直接走人。如果大家hook这个函数的话O(∩_∩)O~
[ 本帖最后由 whypro 于 2010-5-20 22:16 编辑 ] 本帖最后由 whypro 于 2010-5-22 15:22 编辑
先来说说函数int func(int x); /* 声明一个函数 */
int (*f) (int x); /* 声明一个函数指针 */
f=func; /* 将func函数的首地址赋给指针f */
例子:
#include <stdio.h>
//#include "windows.h"
int (__cdecl *myCallBackFun)(int Param1,int Param2);<----指针(函数用法)
int mymax(int a,int b){
return a>b?a:b;
}
int main()
{
int *p; <----指针(普通用法)
int a=10;
p=&a; <------指向变量(普通用法)
int b=20;
int c=0;
c=mymax(a,b);
printf("%d\n",c);
myCallBackFun=mymax;<-----指向函数(函数用法)
printf("%d\n",c);
return 0;
}
其实都是一样的用法,只是内容变了!大家多多对比学习!
再讲讲回调函数看代码:
#include <stdio.h>
typedef void (*callback_t)(void *);
void repeat_three_times(callback_t, void *);
void repeat_three_times(callback_t f, void *para)<-----函数作为参数
{
f(para);
f(para);
f(para);
}
void say_hello(void *str)
{
printf("Hello %s\n", (const char *)str);
}
void count_numbers(void *num)
{
int i;
for(i=1; i<=(int)num; i++)
printf("%d ", i);
putchar('\n');
}
int main(void)
{
repeat_three_times(say_hello, "Guys");<-----把函数作为参数
repeat_three_times(count_numbers, (void *)4);<-----把函数作为参数
return 0;
}
运行结果如下:
Hello Guys
Hello Guys
Hello Guys
1 2 3 4
1 2 3 4
1 2 3 4
Press any key to continue
回调函数:如果参数是一个函数指针,调用者(say_hello,count_numbers)可以传递一个函数的地址给实现者(repeat_three_times),让实现者(repeat_three_times)去调用它,这称为回调函数(Callback Function)。
在GUI编程中异步回调函数更是有普遍的应用,例如为某个按钮注册一个回调函数,当用户点击按钮时调用它。(自己对照vb,vc,delphi的按钮控件运行框架看看,是不是回调呢?)
callback函数 DlgProc = yC.0040290E
汇编中的回调函数DlgProc proc hDlg:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
(假设)对应c版本函数
BOOL CALLBACK MyDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_INITDIALOG:
return TRUE;
case WM_DESTROY:
EndDialog(hDlg, 0);
return TRUE;
}
return FALSE;
}
在回调函数中对应着消息处理函数,我就不多说了。可以参考Windows的消息处理函数
LRESULT CALLBACK WindowProc(
HWND hwnd, // handle of window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
); 写的有深度。感谢。有一点不是很明白
.code
include CryptStuff.ASM
include PER.ASM
这里的两个文件为什么要放在这里,放在头文件前面不是更清晰么? 本帖最后由 whypro 于 2010-5-27 19:44 编辑
include CryptStuff.ASM
include PER.ASM
是自己定义的库,就像c语言里的函数定义在别的头文件中或者自定义在程序的开头。
如果不放在.code内会过不了编译器的! 这个要顶下,值得学习 本帖最后由 whypro 于 2010-5-22 17:51 编辑
其中的 call CryptFile 函数尤为重要!(因为yoda's Crypter加壳软件核心算法都在函数CryptFile中)
对应反汇编如下:
00402B1E|> \57 push edi
00402B1F|.FF75 08 push dword ptr ss:
00402B22|.68 54104000 push yC.00401054
00402B27|.E8 D4EBFFFF call yC.00401700
进入 call yC.00401700 后如下:
00401700/$55 push ebp
00401701|.8BEC mov ebp,esp
00401703|.E8 CB100000 call yC.004027D3 ;随机种子
00401708|.6A 00 push 0 ; /hTemplateFile = NULL
0040170A|.68 80000000 push 80 ; |Attributes = NORMAL
0040170F|.6A 03 push 3 ; |Mode = OPEN_EXISTING
00401711|.6A 00 push 0 ; |pSecurity = NULL
00401713|.6A 03 push 3 ; |ShareMode = FILE_SHARE_READ|FILE_SHARE_WRITE
00401715|.68 000000C0 push C0000000 ; |Access = GENERIC_READ|GENERIC_WRITE
0040171A|.FF75 08 push dword ptr ss: ; |FileName
0040171D|.E8 2A140000 call <jmp.&KERNEL32.CreateFileA> ; \CreateFileA
未完待续 本帖最后由 whypro 于 2010-5-23 08:56 编辑
CryptStuff.ASM 主要负责PE文件的操作 本帖最后由 whypro 于 2010-5-23 08:56 编辑
PER.ASM 文件主要是多态、加密解密。 本帖最后由 whypro 于 2010-5-22 18:04 编辑
这里是网站和源码
Yoda's Protector Source
论坛备份源代码
页:
[1]
2