首页
社区
课程
招聘
[原创]第一阶段第二题我的笨方法+处理的文件(看雪金山2007逆向分析挑战赛)
发表于: 2007-8-27 12:00 12953

[原创]第一阶段第二题我的笨方法+处理的文件(看雪金山2007逆向分析挑战赛)

2007-8-27 12:00
12953

第一阶段第二题我的笨方法+处理的文件(看雪金山2007逆向分析挑战赛)
by aker
16:29 2007-8-26
使用工具:winhex,stud_pe,w32asm,od

如果对pe文件格式一点都不知道的,可以先看看www.pediy.com的资料区的pe格式,我也是现学现卖的:P
另外对windows消息循环机制要有一定的了解。

开始下载后很快就合并成功并出现窗口了,就放下了,感觉应该很容易出来的。今天在论坛上发现提交的人较少,想是不是很难啊,而且我也上不了网了,所以自己动手做了下,发现确实挺烦得,但是我估计我的方法非常笨拙,也有可能是平时这方面作的少,就当是抛砖引玉吧;)希望看到大牛的手笔,特别是shoooo,ccfer等好快的牛,呵呵呵。我找导入表是就这样用眼睛看得,不知道是不是可以写程序判断之类。入口点是合并后用w32asm看得。另外如果文件要重新对齐和重建引入表,估计就更加麻烦了。大家有好方法都介绍下拉。

附件是我合并好并修改好的文件。

1.文件重建

先从其他文件剥下来一个pe文件头,命名为pehead.dat。方法随便,我用的是winhex从一个文件前面剥下一个4k的文件头。方法是在文件头ALT+1,在要选尾部ALT+2,然后再编辑里面另存为phead.dat.

然后按照下面的顺序。

文件大小

rav  - name  size
0000h  - phead  1000h
1000h  - text  6000h
7000h  - rdata  1000h
8000h  - data  3000h
004011F5   |.  BE 94804000         mov esi,bf1.00408094                         ;  ASCII "pediy.com"
........
00401248   |.  8D45 F4             lea eax,dword ptr ss:[ebp-C]
0040124B   |.  8945 D0             mov dword ptr ss:[ebp-30],eax
0040124E   |.  8D45 B0             lea eax,dword ptr ss:[ebp-50]
00401251   |.  BF A0804000         mov edi,bf1.004080A0                         ;  ASCII "pediy.com"
00401256   |.  50                  push eax                                     ; /pWndClass
00401257   |.  897D D4             mov dword ptr ss:[ebp-2C],edi                ; |
0040125A   |.  FF15 0C714000       call dword ptr ds:[<&USER32.RegisterClassA>] ; \RegisterClassA
pediy.com MENU
{
   POPUP "&Help"
   {
      MENUITEM "&About",         1
   }
}
   MENUITEM "&About",   1

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 7
支持
分享
最新回复 (29)
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
学习   学习
2007-8-27 12:04
0
雪    币: 207
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
学习学习!``````````
2007-8-27 12:09
0
雪    币: 151
活跃值: (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
4
一直知道自己对pe结构了解不足,做这个题就表现的很彻底,拼接exe的时间用了好几个小时,然后想把菜单加到资源里也没有成功 ,可喜的是最后还是折腾出来了。下面是简要的分析过程:

从导入表入手,很明显存放在_rdata里面,在偏移0x061C的地方找到

00000618h: B4 76 00 00 00 00 00 00 00 00 00 00 AC 77 00 00 ; 磛..........瑆..

对应的是KERNEL32.DLL,因此这个文件的位置偏移应该是0x7000。

根据各个文件的大小,可以知道其顺序是:

Header:0x1000
_text :0x6000
_rdata:0x7000
_data :0x8000

将他们连接起来,然后随便copy一个exe的头进去,修改如下:

Number of Sections = 3
Size of Code Section = 0x6000
Entry Point RVA = 0x1000(临时)
Section Alignment = 0x1000
File Alignment = 0x1000
Import Table Address = 0x7618(关键)
Import Table Size = 0x50

保存以后用OD载入,查找函数GetVersion(多半是VC的程序,就猜它),得到入口点,修改

Entry Point RVA = 0x1527(修正)

exe拼接好了,然后开始diy。在创建窗口以后跳到自己的空间

00401282   .  FF15 10714000          CALL    NEAR DWORD PTR [<&USER32.CreateW>; \CreateWindowExA
00401288   .- E9 73770000            JMP     00408A00

先用高级语言写了个样子:
hMenu := CreateMenu;
hPopup := CreateMenu;
AppendMenu(hPopup, MF_POPUP, 555, '&About');
AppendMenu(hMenu, MF_POPUP, hPopup, '&Help');
SetMenu(Handle, hMenu);

然后在OD里面直接修改如下:
00408A00    60                       PUSHAD
00408A01    8BF8                     MOV     EDI, EAX
00408A03    68 F5894000              PUSH    004089F5                         ; ASCII "user32.dll"
00408A08    FF15 6C704000            CALL    NEAR DWORD PTR [<&KERNEL32.LoadL>; kernel32.LoadLibraryA
00408A0E    A3 BC894000              MOV     DWORD PTR [4089BC], EAX
00408A13    68 EA894000              PUSH    004089EA                         ; ASCII "CreateMenu"
00408A18    FF35 BC894000            PUSH    DWORD PTR [4089BC]
00408A1E    FF15 A0704000            CALL    NEAR DWORD PTR [<&KERNEL32.GetPr>; kernel32.GetProcAddress
00408A24    A3 B0894000              MOV     DWORD PTR [4089B0], EAX
00408A29    68 DE894000              PUSH    004089DE                         ; ASCII "AppendMenuA"
00408A2E    FF35 BC894000            PUSH    DWORD PTR [4089BC]
00408A34    FF15 A0704000            CALL    NEAR DWORD PTR [<&KERNEL32.GetPr>; kernel32.GetProcAddress
00408A3A    A3 B4894000              MOV     DWORD PTR [4089B4], EAX
00408A3F    68 D6894000              PUSH    004089D6                         ; ASCII "SetMenu"
00408A44    FF35 BC894000            PUSH    DWORD PTR [4089BC]
00408A4A    FF15 A0704000            CALL    NEAR DWORD PTR [<&KERNEL32.GetPr>; kernel32.GetProcAddress
00408A50    A3 B8894000              MOV     DWORD PTR [4089B8], EAX
00408A55    FF15 B0894000            CALL    NEAR DWORD PTR [4089B0]
00408A5B    8BD8                     MOV     EBX, EAX
00408A5D    FF15 B0894000            CALL    NEAR DWORD PTR [4089B0]
00408A63    8BF0                     MOV     ESI, EAX
00408A65    68 CF894000              PUSH    004089CF                         ; ASCII "&About"
00408A6A    68 55050000              PUSH    555                              ; 菜单的ID
00408A6F    6A 10                    PUSH    10
00408A71    56                       PUSH    ESI
00408A72    FF15 B4894000            CALL    NEAR DWORD PTR [4089B4]
00408A78    68 C8894000              PUSH    004089C8                         ; ASCII "&Help"
00408A7D    56                       PUSH    ESI
00408A7E    6A 10                    PUSH    10
00408A80    53                       PUSH    EBX
00408A81    FF15 B4894000            CALL    NEAR DWORD PTR [4089B4]
00408A87    53                       PUSH    EBX
00408A88    57                       PUSH    EDI
00408A89    FF15 B8894000            CALL    NEAR DWORD PTR [4089B8]
00408A8F    61                       POPAD
00408A90    FF75 14                  PUSH    DWORD PTR [EBP+14]
00408A93    8BF8                     MOV     EDI, EAX                         ; 恢复破坏的代码
00408A95  - E9 F387FFFF              JMP     0040128D                         ; 跳回原来空间

处理菜单的事件在消息循环里修改:
004012DB   .  8B45 0C                MOV     EAX, DWORD PTR [EBP+C]
004012DE   .  48                     DEC     EAX
004012DF   .  48                     DEC     EAX
004012E0   .  74 68                  JE      SHORT 0040134A
004012E2   .- E9 19780000            JMP     00408B00

跳到自己的空间里,判断一下是不是WM_COMMAND消息,
00408B00    2D 0F010000              SUB     EAX, 10F
00408B05    74 11                    JE      SHORT 00408B18
00408B07    05 0C010000              ADD     EAX, 10C
00408B0C  - 0F84 2288FFFF            JE      00401334
00408B12  - E9 D087FFFF              JMP     004012E7
00408B17    90                       NOP

然后判断一下是不是菜单555触发的,如果是就弹出对话框,
00408B18    817D 10 55050000         CMP     DWORD PTR [EBP+10], 555
00408B1F    75 18                    JNZ     SHORT 00408B39
00408B21    90                       NOP
00408B22    68 40200100              PUSH    12040
00408B27    68 C08A4000              PUSH    00408AC0                         ; ASCII "pediy"
00408B2C    68 C68A4000              PUSH    00408AC6
00408B31    E8 8ECEFFFF              CALL    004059C4
00408B36    83C4 0C                  ADD     ESP, 0C
00408B39  - E9 1488FFFF              JMP     00401352

注意的是exe本身就提供了MessageBoxA的调用,可以直接用函数4059C4,参数是:
消息内容: string;
窗口标题: string;
窗口ICON: Integer;

调用完后配平堆栈,返回消息循环处,收工。

这题比上题难多了,要不是有看雪精华、exescope、lordpe、winhex、ue、计算器、delphi、vc、msdn、baidu、google等的大力协助,几乎无法完成。
2007-8-27 12:11
0
雪    币: 6051
活跃值: (1441)
能力值: ( LV15,RANK:1473 )
在线值:
发帖
回帖
粉丝
5
强人啊,支持一下

学习中。。。
2007-8-27 12:11
0
雪    币: 2134
活跃值: (14)
能力值: (RANK:170 )
在线值:
发帖
回帖
粉丝
6
呵呵,我也觉得这题难些,主要是基础知识点太多了;)
2007-8-27 12:33
0
雪    币: 109
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
7
觉得这里改比较好:

将原窗口消息处理函数里这段代码的 call ds:DefWindowProcA

.text:004012EC                 push    [ebp+arg_C]
.text:004012EF                 push    [ebp+arg_8]
.text:004012F2                 push    [ebp+arg_4]
.text:004012F5                 push    [ebp+arg_0]
.text:004012F8                 call    ds:DefWindowProcA
.text:004012FE                 jmp     short locret_401354

改成call MyWndProc,函数代码如下:

LRESULT CALLBACK MyWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  if ( message == WM_COMMAND && wParam == 0x68)
  {
    MessageBox(NULL,"看雪论坛.珠海金山2007逆向分析挑战赛\r\nhttp://www.pediy.com","pediy",0x40);
    return 0;
  }

  return DefWindowProc(hWnd, message, wParam, lParam);
}

还能多出一个空余字节 :)
2007-8-27 12:38
0
雪    币: 6075
活跃值: (2236)
能力值: (RANK:1060 )
在线值:
发帖
回帖
粉丝
8
这个题跟第一题不能比啊,纯粹比手快。
2007-8-27 13:09
0
雪    币: 295
活跃值: (461)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
9
这次比赛造就了不少精华贴呀!
2007-8-27 13:16
0
雪    币: 13097
活跃值: (4097)
能力值: ( LV15,RANK:1673 )
在线值:
发帖
回帖
粉丝
10
偶也来凑下热闹,相同的东东不贴了,只贴上偶Patch的代码吧:

找一空地写入下面的代码:
00406B80      817C24 08 11010000    cmp     dword ptr [esp+8], 111          ;WM_COMMAND
00406B88    ^ 0F85 47A7FFFF         jnz     004012D5
00406B8E      66:837C24 0C 68       cmp     word ptr [esp+C], 68            ;About命令ID,资源文件自定义时的值
00406B94    ^ 0F85 3BA7FFFF         jnz     004012D5
00406B9A      60                    pushad
00406B9B      6A 40                 push    40
00406B9D      68 8C804000           push    0040808C                         ;  ASCII "pediy"
00406BA2      68 C06B4000           push    00406BC0
00406BA7      E8 18EEFFFF           call    004059C4                          ;延时载入的MessageBox ,应该就是VC静态连接的AfxMessageBox吧
00406BAC      83C4 0C               add     esp, 0C
00406BAF      61                    popad
00406BB0      33C0                  xor     eax, eax
00406BB2      C2 1000               retn    10

00406BC0  BF B4 D1 A9 C2 DB CC B3 2E D6 E9 BA A3 BD F0  .看雪论坛.珠海金
00406BCF  C9 BD 32 30 30 37 C4 E6 CF F2 B7 D6 CE F6 CC F4  山2007逆向分析挑
00406BDF  D5 BD C8 FC 0D 0A 68 74 74 70 3A 2F 2F 77 77 77  战赛..http://www
00406BEF  2E 70 65 64 69 79 2E 63 6F 6D 00                 .pediy.com.

并改 RegisterClass 窗口消息处理入口地址:
0040121A  |.  C745 B4 D5124>mov     dword ptr [ebp-4C], 004012D5           ;原消息处理入口地址
为:
0040121A      C745 B4 806B4000      mov     dword ptr [ebp-4C], 00406B80
2007-8-27 13:47
0
雪    币: 325
活跃值: (97)
能力值: ( LV13,RANK:530 )
在线值:
发帖
回帖
粉丝
11
第一题,算法太难。 这道题感觉的确是比手快。
2007-8-27 13:55
0
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
谢谢,学习了
2007-8-27 14:06
0
雪    币: 154
活跃值: (80)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
13
动手做一遍,的确有不少收获
2007-8-27 14:37
0
雪    币: 120
活跃值: (58)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
我的方法跟请哥慢捂的差不多。不过感觉像Aker那种直接加资源快一些,可惜我当时不知道是否能实现。现在看起来果然加资源比写汇编码快多了。

十分佩服在一、两个小时就搞定第二题的高手。
2007-8-27 16:21
0
雪    币: 2134
活跃值: (14)
能力值: (RANK:170 )
在线值:
发帖
回帖
粉丝
15
[QUOTE=null;351224]觉得这里改比较好:

将原窗口消息处理函数里这段代码的 call ds:DefWindowProcA

.text:004012EC                 push    [ebp+arg_C]
.text:004012EF                 push    [eb...[/QUOTE]

对,这样就快了,学习了,谢谢分享;)
2007-8-27 16:39
0
雪    币: 424
活跃值: (10)
能力值: ( LV9,RANK:850 )
在线值:
发帖
回帖
粉丝
16
第一题``算法难逆呀``
帮Aker大哥顶上去,哦也`
2007-8-27 16:48
0
雪    币: 328
活跃值: (10)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
17
大菜水平很够的。
不过俺们这些70末的人占个便宜就是童年比较丰富。
小时候玩过9连环就不难找到规律。
2007-8-27 17:00
0
雪    币: 6075
活跃值: (2236)
能力值: (RANK:1060 )
在线值:
发帖
回帖
粉丝
18
DefWindowProc + AfxMessageBox + wc.lpszMenuName = 王道
2007-8-27 17:04
0
雪    币: 424
活跃值: (10)
能力值: ( LV9,RANK:850 )
在线值:
发帖
回帖
粉丝
19
承蒙seya老师夸奖,呵呵~
2007-8-27 17:49
0
雪    币: 424
活跃值: (10)
能力值: ( LV9,RANK:850 )
在线值:
发帖
回帖
粉丝
20
f+o+r+g+o+t=王道
2007-8-27 17:51
0
雪    币: 202
活跃值: (77)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
21
我怎么就没有想到___crtMessageBoxA,差距呀差距呀
2007-8-27 18:20
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
请大侠指教Import Table Address和Entry Point RVA怎么看出来的。。
2007-8-27 18:38
0
雪    币: 1505
能力值: (RANK:210 )
在线值:
发帖
回帖
粉丝
23
偶也偶的贴出来献丑一下,写的很烂
00406BB6   > \FF15 98B04000 CALL DWORD PTR DS:[<&user32.CreateMenu>]                                     
00406BBC   .  8BF0          MOV ESI,EAX
00406BBE   .  68 AF6B4000   PUSH bithaha.00406BAF                                                         
00406BC3   .  68 00010000   PUSH 100                                                                      
00406BC8   .  6A 00         PUSH 0                                                                          
00406BCA   .  50            PUSH EAX                                                                        
00406BCB   .  FF15 9CB04000 CALL DWORD PTR DS:[<&user32.AppendMenuA>]                                       00406BD1   .  FF15 98B04000 CALL DWORD PTR DS:[<&user32.CreateMenu>]                                       
00406BD7   .  68 A96B4000   PUSH bithaha.00406BA9                                                          
00406BDC   .  56            PUSH ESI                                                                       
00406BDD   .  8BF0          MOV ESI,EAX                                                                   
00406BDF   .  6A 10         PUSH 10                                                                       
00406BE1   .  50            PUSH EAX                                                                        
00406BE2   .  FF15 9CB04000 CALL DWORD PTR DS:[<&user32.AppendMenuA>]                                      00406BE8   .  6A 00         PUSH 0
00406BEA   .  53            PUSH EBX
00406BEB   .  56            PUSH ESI
00406BEC   .  B8 00000080   MOV EAX,80000000
00406BF1   .  33F6          XOR ESI,ESI
00406BF3   .^ E9 79A6FFFF   JMP bithaha.00401271//返回到createwindow前
00406BF8   >  3D 11010000   CMP EAX,111
00406BFD   .  75 2D         JNZ SHORT bithaha.00406C2C
00406BFF   .  90            NOP
00406C00   .  90            NOP
00406C01   .  90            NOP
00406C02   .  90            NOP
00406C03   .  56            PUSH ESI
00406C04   .  8B75 10       MOV ESI,DWORD PTR SS:[EBP+10]
00406C07   .  81FE 00010000 CMP ESI,100
00406C0D   .  5E            POP ESI
00406C0E   .  75 1C         JNZ SHORT bithaha.00406C2C
00406C10   .  90            NOP
00406C11   .  90            NOP
00406C12   .  90            NOP
00406C13   .  6A 00         PUSH 0                                                                          
00406C15   .  68 976B4000   PUSH bithaha.00406B97                                                        
00406C1A   .  68 746B4000   PUSH bithaha.00406B74                                                          
00406C1F   .  6A 00         PUSH 0                                                                         
00406C21   .  FF15 A0B04000 CALL DWORD PTR DS:[<&user32.MessageBoxA>]                                    
00406C27   .^ E9 28A7FFFF   JMP bithaha.00401354
00406C2C   >  48            DEC EAX
00406C2D   .  48            DEC EAX
00406C2E   .^ 0F84 16A7FFFF JE bithaha.0040134A
00406C34   .  83E8 03       SUB EAX,3
00406C37   .^ E9 A9A6FFFF   JMP bithaha.004012E5//返回到窗口回调函数
2007-8-27 19:16
0
雪    币: 223
活跃值: (25)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
24
我的处理Pe文件代码,唉入口点通过Peid的特征码找的,可是就是那个菜单没做出来,差啊。。。

unit PEHandler;

interface

uses
  Classes, Forms, sysutils, windows;

type

{PE导出表声明}
  PImageExportDirectory = ^TImageExportDirectory;
  TImageExportDirectory = packed record
    Characteristics: DWORD;
    TimeDateStamp: DWORD;
    MajorVersion: WORD;
    MinorVersion: WORD;
    Name: DWORD;
    Base: DWORD;
    NumberOfFunctions: DWORD;
    NumberOfNames: DWORD;
    AddressOfFunctions: DWORD;
    AddressOfNames: DWORD;
    AddressOfNameOrdinals: DWORD;
  end;

  PImportByName=^TImportByName;
  TImportByName =Packed  record
    ProcedureHint: word;
    ProcedureName: array[0..1]of char;
  end;

  PImageImportDescriptor = ^TImageImportDescriptor;
  TImageImportDescriptor = packed record
    OriginalFirstThunk: DWord;
    TimeDateStamp  : DWord;
    ForwarderChain : DWord;
    DLLName        : DWord;
    FirstThunk     : DWord;
  end;

  PImageThunkData=^TImageThunkData;
  TImageThunkData = record
  case integer of
    1:( ForwarderString : DWord; );
    2:( Function_       : DWord; );
    3:( Ordinal         : DWord; );
    4:( AddressOfData   : DWord; );
  end;
  PImageBaseRelocation=^TImageBaseRelocation;
  TImageBaseRelocation=Packed Record
     VirtualAddress: Dword;
     SizeOfBlock: Dword;
     TypeOffset: array[0..1] of Word;
  end;

  TPESection = record    //自定义
    ObjectName: string;
    Address: PChar;
    PhysicalSize: Integer;
//    VirtualSize: Integer;
//    Characteristics: Cardinal;
    PointerToRawData: Integer;
  end;

  TNameOrID = (niName, niID);  
  TPEImport = record
    NameOrID: TNameOrID;
    Name: string;
    ID: Integer;
//    PAddress: PChar; {指向导入表函数用于执行此函数}
  end;
  TPEImports = record {记录一个Dll文件所调用的函数个数}
    DLLName: string;
    Entries: array of TPEImport; {函数数据}
  end;

  TPEExport = record
    Name: string;
    RelativeID: Integer;
    ID: Integer;
    Address: DWORD;{相对地址}
  end;

  TPEHandler = class(TThread)
  private
    { Private declarations }
    FPE, FTmp: TMemoryStream;
    FSectionFiles: array[0..3] of string;
    FSectionSizes: array[0..3] of integer;
    FImportCount: integer;
    FImportVA: integer;
    FIAT: integer;
    FIATSize: integer;
    procedure HandlerImport;
    function GetEntryPoint: integer;
    procedure GetPEHead;
    Procedure FillSection;
    procedure ChangPEHead;
    procedure ShowInfo(Info: string);
  protected
    procedure Execute; override;
  end;

implementation

uses uMain;

{ TPEHandler }

procedure TPEHandler.ChangPEHead;
var
  ImageDosHeader:     TImageDosHeader;
  ImageNtHeaders:     TImageNtHeaders;
  ImageSectionHeader: TImageSectionHeader;
  Sections: array of TImageSectionHeader;
  i, RVA, EP: integer;
begin
  FPe.Seek(0, soBeginning);
  FPE.ReadBuffer(ImageDosHeader, sizeof(ImageDosHeader));
  FPE.Position := ImageDosHeader._lfanew;
  FPE.ReadBuffer(ImageNtHeaders,sizeof(TImageNtHeaders));
//////////////////////////////////////////////////////////
//修改如下:

  //File Header
  ImageNtHeaders.FileHeader.NumberOfSections := 4;

  //OptionalHeader
  ImageNtHeaders.OptionalHeader.SizeOfCode := FSectionSizes[0];
  ImageNtHeaders.OptionalHeader.SizeOfImage := FPE.Size;
  //ImageNtHeaders.OptionalHeader.SizeOfImage := FPE.Size - $1000;

  EP := GetEntryPoint;
  ImageNtHeaders.OptionalHeader.AddressOfEntryPoint := EP;
  ShowInfo('PE entry Point: 0x' + IntToHex(EP, 8));

  //修改输入表
  HandlerImport;

  for i := 0 to 15 do
  begin
    ImageNtHeaders.OptionalHeader.DataDirectory[i].VirtualAddress := 0;
    ImageNtHeaders.OptionalHeader.DataDirectory[i].Size := 0;
  end;

  //输入表
  ImageNtHeaders.OptionalHeader.DataDirectory[1].VirtualAddress := FImportVA;
  ImageNtHeaders.OptionalHeader.DataDirectory[1].Size := (FImportCount + 1) *
    sizeof(TImageImportDescriptor);

  //输入地址表
  ImageNtHeaders.OptionalHeader.DataDirectory[12].VirtualAddress := FIAT;
  ImageNtHeaders.OptionalHeader.DataDirectory[12].Size := $124;

//////////////////////////////////////////////////////////////////////////////

  //写 改好的信息
  FPE.Position := ImageDosHeader._lfanew;
  FPE.WriteBuffer(ImageNtHeaders,sizeof(TImageNtHeaders));

  SetLength(Sections, 4);

  RVA := $1000;
  for i := 0 to 3 do
  begin
    Move(PChar(FSectionFiles[i])^,Sections[i].Name, length(FSectionFiles[i]));
    Sections[i].Misc.VirtualSize := FSectionSizes[i];
    Sections[i].VirtualAddress := RVA;
    RVA := RVA + FSectionSizes[i];
    Sections[i].SizeOfRawData := FSectionSizes[i];
    Sections[i].PointerToRawData := Sections[i].VirtualAddress;
    Sections[i].PointerToRelocations := 0;
    Sections[i].PointerToLinenumbers := 0;
    Sections[i].NumberOfRelocations := 0;
    Sections[i].NumberOfLinenumbers := 0;
    case i of
    0: Sections[i].Characteristics := $C0000060;
    1: Sections[i].Characteristics := $C0000040;
    2: Sections[i].Characteristics := $C00000C0;
    3:
    begin
      Sections[i].Characteristics := $C00000C0;
      //Sections[i].VirtualAddress := $18000;
    end;

    end;
    FPE.WriteBuffer(Sections[i],sizeof(TImageSectionHeader));
  end;

  Fillchar(ImageSectionHeader, sizeof(TImageSectionHeader), 0);
  FPE.WriteBuffer(ImageSectionHeader,sizeof(TImageSectionHeader));

  ShowInfo('change Pe Head');
end;

procedure TPEHandler.Execute;
begin
  FPE := TMemoryStream.Create;
  try

    FSectionFiles[0] := '_text';
    FSectionFiles[1] := '_rdata';
    FSectionFiles[2] := '_data';
    FSectionFiles[3] := '_rsrc';

    FTmp := TMemoryStream.Create;
    try
      GetPEHead;
      FillSection;
      ChangPEHead;
      FPE.SaveToFile('New.exe');
    finally
      FTmp.Free;
    end;

  finally
    FPE.Free;
  end;

end;

procedure TPEHandler.FillSection;
var
  rmod, i, wcount: integer;

begin
  for i := 0 to 3 do
  begin
    FTmp.LoadFromFile(FSectionFiles[i]);
    rMod := FTmp.Size mod $1000;
    if rMod <> 0 then
    begin
      FTmp.Size := FTmp.Size + $1000 - rMod;
    end;
    FSectionSizes[i] := FTmp.Size;

    FPe.Seek(0, soEnd);
    wcount := FPe.Write(PChar(FTmp.Memory)^, FTmp.Size);
    ShowInfo('Fill Section ' + FSectionFiles[i] + ', size: 0x'
      + IntToHex(WCount, 8));
  end;

end;

function TPEHandler.GetEntryPoint: integer;
const
  VCEP: array[0..5] of byte = ($55, $8B, $EC, $6A, $FF, $68);
var
  rByte: byte;
  i: integer;
  bFind: Boolean;
begin
  Result := 0;
  FPe.Position := $1000;
  while FPe.Position < $1000 + FSectionSizes[0] do
  begin
    bFind := true;
    for i := 0 to 5 do
    begin
      FPe.ReadBuffer(rByte, 1);
      if rByte <> VCEP[i] then
      begin
        FPe.Position := FPe.Position - i;
        bFind := false;
        Break;
      end;
    end;
    if bfind then
    begin
      Result := FPe.Position - 6;
      exit;
    end;

  end;
end;

procedure TPEHandler.GetPEHead;
begin
  FTmp.LoadFromFile('1.exe');
  FPe.Size := $1000;
  FPe.Seek(0, soBeginning);
  FTmp.Size := $1000;
  FPe.LoadFromStream(FTmp);
  ShowInfo('Get Pe Head from: ''1.exe''');

end;

procedure TPEHandler.HandlerImport;
const
  LastRVA: integer = $0654;
var
  iRVA, SectionVA, LastVA, DllVA: integer;
  ImageImportDescriptor: TImageImportDescriptor;
  DLLName: array[1..32] of char;
  DllCount: integer;
begin
  SectionVA := FSectionSizes[0]  + $1000;
  LastVA := SectionVA + LastRVA;
  FImportCount := 0;
  FIAT := $0FFFFFFF;
  while True do
  begin
    FPE.Position := LastVA - (FImportCount + 1) * sizeof(TImageImportDescriptor);
    FPe.ReadBuffer(ImageImportDescriptor, sizeof(TImageImportDescriptor));
    DllVA := ImageImportDescriptor.DLLName;
    if (Integer(DllVA) > sectionVA + FSectionSizes[1]) or
    (Integer(DllVA) < sectionVA) then Break;
   
    if FIAT > ImageImportDescriptor.FirstThunk then
      FIAT := ImageImportDescriptor.FirstThunk;

    ShowInfo('IAT: 0x' + IntToHex(ImageImportDescriptor.FirstThunk, 8));

    FPE.Position := DLLVA;
    FPE.ReadBuffer(DLLName, 32);
    ShowInfo('Import Dll Name:' + DllName);
    Inc(FImportCount);
  end;
  ShowInfo('Import Count:' + IntToStr(FImportCount));
  FImportVA := SectionVA + LastRVA - FImportCount * sizeof(TImageImportDescriptor);
  ShowInfo('Import VA: 0x' + IntToHex(FImportVA, 8));
end;

procedure TPEHandler.ShowInfo(Info: string);
begin
  frmMain.lbInfo.Items.Add(Info);
  Application.ProcessMessages;
end;

end.
2007-8-27 20:03
0
雪    币: 159
活跃值: (339)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
25
还是LordPE好用Slpit和unsplit,题目中的文件感觉就是被出题者用来剥出来的
2007-8-27 22:07
0
游客
登录 | 注册 方可回帖
返回
//