whypro 发表于 2010-5-20 21:03:32

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-20 21:16:10

本帖最后由 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-20 22:08:20

本帖最后由 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
   );

kelvar 发表于 2010-5-20 22:20:25

写的有深度。感谢。有一点不是很明白

.code
include CryptStuff.ASM
include PER.ASM

这里的两个文件为什么要放在这里,放在头文件前面不是更清晰么?

whypro 发表于 2010-5-21 06:29:41

本帖最后由 whypro 于 2010-5-27 19:44 编辑

include CryptStuff.ASM
include PER.ASM
是自己定义的库,就像c语言里的函数定义在别的头文件中或者自定义在程序的开头。
如果不放在.code内会过不了编译器的!

月之精灵 发表于 2010-5-21 15:23:38

这个要顶下,值得学习

whypro 发表于 2010-5-22 15:15:00

本帖最后由 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-22 17:43:09

本帖最后由 whypro 于 2010-5-23 08:56 编辑

CryptStuff.ASM 主要负责PE文件的操作

whypro 发表于 2010-5-22 17:45:27

本帖最后由 whypro 于 2010-5-23 08:56 编辑

PER.ASM 文件主要是多态、加密解密。

whypro 发表于 2010-5-22 17:51:57

本帖最后由 whypro 于 2010-5-22 18:04 编辑

这里是网站和源码
Yoda's Protector Source
论坛备份源代码

页: [1] 2
查看完整版本: yC 逆着看