飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 8773|回复: 17

[原创] yC 逆着看

  [复制链接]
  • TA的每日心情
    慵懒
    2019-3-12 17:25
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    发表于 2010-5-20 21:03:32 | 显示全部楼层 |阅读模式
    本帖最后由 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
            LOCAL  hDrop : 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 [eax] == 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
                     OR  EDI, 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 编辑 ]

    评分

    参与人数 1飘云币 +40 收起 理由
    月之精灵 + 40 您的贴子很精彩,希望能再次分享!

    查看全部评分

    PYG19周年生日快乐!
  • TA的每日心情
    慵懒
    2019-3-12 17:25
  • 签到天数: 3 天

    [LV.2]偶尔看看I

     楼主| 发表于 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:[401000],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 编辑 ]
    PYG19周年生日快乐!
  • TA的每日心情
    慵懒
    2019-3-12 17:25
  • 签到天数: 3 天

    [LV.2]偶尔看看I

     楼主| 发表于 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
       );
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2010-5-20 22:20:25 | 显示全部楼层
    写的有深度。感谢。有一点不是很明白
    .code
    include CryptStuff.ASM
    include PER.ASM

    这里的两个文件为什么要放在这里,放在头文件前面不是更清晰么?
    PYG19周年生日快乐!
  • TA的每日心情
    慵懒
    2019-3-12 17:25
  • 签到天数: 3 天

    [LV.2]偶尔看看I

     楼主| 发表于 2010-5-21 06:29:41 | 显示全部楼层
    本帖最后由 whypro 于 2010-5-27 19:44 编辑

    include CryptStuff.ASM
    include PER.ASM
    是自己定义的库,就像c语言里的函数定义在别的头文件中或者自定义在程序的开头。
    如果不放在.code内会过不了编译器的!
    PYG19周年生日快乐!
  • TA的每日心情
    开心
    2015-8-3 23:07
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    发表于 2010-5-21 15:23:38 | 显示全部楼层
    这个要顶下,值得学习
    PYG19周年生日快乐!
  • TA的每日心情
    慵懒
    2019-3-12 17:25
  • 签到天数: 3 天

    [LV.2]偶尔看看I

     楼主| 发表于 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:[ebp+8]
    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:[ebp+8]                         ; |FileName
    0040171D  |.  E8 2A140000   call <jmp.&KERNEL32.CreateFileA>                  ; \CreateFileA

    未完待续
    PYG19周年生日快乐!
  • TA的每日心情
    慵懒
    2019-3-12 17:25
  • 签到天数: 3 天

    [LV.2]偶尔看看I

     楼主| 发表于 2010-5-22 17:43:09 | 显示全部楼层
    本帖最后由 whypro 于 2010-5-23 08:56 编辑

    CryptStuff.ASM 主要负责PE文件的操作
    PYG19周年生日快乐!
  • TA的每日心情
    慵懒
    2019-3-12 17:25
  • 签到天数: 3 天

    [LV.2]偶尔看看I

     楼主| 发表于 2010-5-22 17:45:27 | 显示全部楼层
    本帖最后由 whypro 于 2010-5-23 08:56 编辑

    PER.ASM 文件主要是多态、加密解密。
    PYG19周年生日快乐!
  • TA的每日心情
    慵懒
    2019-3-12 17:25
  • 签到天数: 3 天

    [LV.2]偶尔看看I

     楼主| 发表于 2010-5-22 17:51:57 | 显示全部楼层
    本帖最后由 whypro 于 2010-5-22 18:04 编辑

    这里是网站和源码
    Yoda's Protector Source
    论坛备份源代码
    yC1.2.zip (23.85 KB, 下载次数: 1)
    yC1.3src.zip (48.36 KB, 下载次数: 1)
    PYG19周年生日快乐!
    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

    快速回复 返回顶部 返回列表