• 标 题:一个程序的开机补丁
  • 作 者:peansen
  • 时 间:004-11-19,12:02
  • 链 接:http://bbs.pediy.com

TUNet是我学校的一个客户端软件,里面包括两个协议端口认证和网关的认证协议,至于协议部分我就不多说,很多同学反映没有开机自动启动的功能。我今天想说一下我打的一个开机补丁。也是对MFC的一次实践吧。
现在该文件夹下加一个配置文件
peansen.ini
内容如下:
[patch]
AUTORUN=1
检查输入表知道我们还需要一个GetPrivateProfileIntA函数的输入项,于是添加之(具体做法很多,可以用工具)
首先我想把整个程序的状况说一下:

->Section Header Table
   1. item:
    Name:                  .text
    VirtualSize:           0x0002E506
    VirtualAddress:        0x00001000
    SizeOfRawData:         0x0002F000
    PointerToRawData:      0x00001000
    PointerToRelocations:  0x00000000
    PointerToLinenumbers:  0x00000000
    NumberOfRelocations:   0x0000
    NumberOfLinenumbers:   0x0000
    Characteristics:       0x60000020
    (CODE, EXECUTE, READ)

   2. item:
    Name:                  .rdata
    VirtualSize:           0x0000AA40
    VirtualAddress:        0x00030000
    SizeOfRawData:         0x0000B000
    PointerToRawData:      0x00030000
    PointerToRelocations:  0x00000000
    PointerToLinenumbers:  0x00000000
    NumberOfRelocations:   0x0000
    NumberOfLinenumbers:   0x0000
    Characteristics:       0xC0000040
    (INITIALIZED_DATA, READ, WRITE)

   3. item:
    Name:                  .data
    VirtualSize:           0x0000ED04
    VirtualAddress:        0x0003B000
    SizeOfRawData:         0x00007000
    PointerToRawData:      0x0003B000
    PointerToRelocations:  0x00000000
    PointerToLinenumbers:  0x00000000
    NumberOfRelocations:   0x0000
    NumberOfLinenumbers:   0x0000
    Characteristics:       0xC0000040
    (INITIALIZED_DATA, READ, WRITE)

   4. item:
    Name:                  .rsrc
    VirtualSize:           0x00066C40
    VirtualAddress:        0x0004A000
    SizeOfRawData:         0x00067000
    PointerToRawData:      0x00042000
    PointerToRelocations:  0x00000000
    PointerToLinenumbers:  0x00000000
    NumberOfRelocations:   0x0000
    NumberOfLinenumbers:   0x0000
    Characteristics:       0x40000040
    (INITIALIZED_DATA, READ)

   5. item:
    Name:                  .gda
    VirtualSize:           0x00001000
    VirtualAddress:        0x000B1000
    SizeOfRawData:         0x00001000
    PointerToRawData:      0x000A9000
    PointerToRelocations:  0xFFF9F2FD
    PointerToLinenumbers:  0x00000000
    NumberOfRelocations:   0x0000
    NumberOfLinenumbers:   0x0000
    Characteristics:       0xE0000020
    (CODE, EXECUTE, READ, WRITE)
先给她加上一个复选框,id=0x5210
然后找到她的消息处理循环,因为那个对话框中的很多edit需要初始化,我于是就借助其中一个在初始化的时候同时也处理我加上去的复选框的初始化过程。根据section的结构,我们在程序里找到很多空白。0x2f510~0x30000都是空白,我们把一些只读字符串放在这边。从0x2f900开始放如下字符串
2E5C5C5045414E53454E2E696E690000706174636800000000000000000000004155544F52554E000000000000000000534F4654574152455C5C4D6963726F736F66745C5C57696E646F77735C5C43757272656E7456657273696F6E5C5C52756E0000000000000054554E455400000000310030000000000000000000000000(这些是16进制值)
分别是:.\\PEANSEN.ini
patch
SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run
TUNET
1  0,和上面的16进制值对号入座就好了
找到了我们要打补丁的地方:0x425cd(不管是初始化还是消息处理都好经过它)代码如下:
B8 5C F0 42 00                mov eax, offset loc_42F05C
.text:00425BF9 E8 3A 2F FF FF                call sub_418B38
.text:00425BFE 83 EC 54                      sub esp, 54h
.text:00425C01 83 65 F0 00                   and dword ptr [ebp-10h], 0
.text:00425C05 53                            push ebx
.text:00425C06 8B 5D 08                      mov ebx, [ebp+8]
.text:00425C09 56                            push esi
.text:00425C0A 57                            push edi
.text:00425C0B 81 FB 11 01 00 00             cmp ebx, 111h
.text:00425C11 8B F9                         mov ediecx
.text:00425C13 75 18                         jnz short loc_425C2D
.text:00425C15 FF 75 10                      push dword ptr [ebp+10h]控件handle-------从这边开始折向补丁处
.text:00425C18 8B 07                         mov eax, [edi]
.text:00425C1A FF 75 0C                      push dword ptr [ebp+0Ch]控件id
.text:00425C1D FF 50 78                      call dword ptr [eax+78h] ; 这是cmd命令的开始
.text:00425C20 85 C0                         test eaxeax
.text:00425C22 0F 84 55 01 00 00             jz loc_425D7D
.text:00425C28 E9 1D 04 00 00                jmp loc_42604A
打补丁后的
00425C13    . /75 18                     jnz short TUNet306.00425C2D
00425C15    . |E9 06990000               jmp TUNet306.0042F520----跳到我们的处理空间
00425C1A    > |FF75 0C                   push dword ptr ss:[ebp+C]
00425C1D    . |FF50 78                   call dword ptr ds:[eax+78]
00425C20    . |85C0                      test eax,eax
补丁的主要代码:
每一段返回都要经过这边,恢复堆栈,加上原来上面用跳转指令被覆盖的代码
0042F510    > /61                        popad
0042F511    . |FF7424 10                 push dword ptr ss:[esp+10]
0042F515    . |8B07                      mov eax,dword ptr ds:[edi]
0042F517    .^|E9 FE66FFFF               jmp TUNet306.00425C1A
0042F51C      |00                        db 00
0042F51D      |00                        db 00
0042F51E      |00                        db 00
0042F51F      |00                        db 00
我们是从上面跳到这边的:
0042F520    > |60                        pushad
0042F521    . |8B45 0C                   mov eax,dword ptr ss:[ebp+C]
0042F524    . |3D 16520004               cmp eax,4005216---抓住id=0x5216的初始化过程来初始化我们自己的复选框
0042F529    . |74 08                     je short TUNet306.0042F533
0042F52B    . |66:3D 1052                cmp ax,5210----自己的消息处理过程
0042F52F    . |74 4F                     je short TUNet306.0042F580
0042F531    .^ EB DD                     jmp short TUNet306.0042F510
复选框的初始化过程
0042F533    > |FF75 10                   push dword ptr ss:[ebp+10]                            ; /hWnd
0042F536    . |FF15 E8034300             call dword ptr ds:[<&USER32.GetParent>]               ; \GetParent
因为我们知道我们所抓住的id=0x5216的控件的句柄,通过它来获得id=0x5210的handle(用getparent函数和GetDlgItem函数)
0042F53C    . |68 10520000               push 5210                                             ; /ControlID = 5210 (21008.)
0042F541    . |50                        push eax                                              ; |hWnd
0042F542    . |FF15 74034300             call dword ptr ds:[<&USER32.GetDlgItem>]              ; \GetDlgItem
0042F548    . |50                        push eax
0042F549    . |68 00F94200               push TUNet306.0042F900                                ; /IniFileName = ".\\PEANSEN.ini"
0042F54E    . |6A 00                     push 0                                                ; |Default = 0
0042F550    . |68 20F94200               push TUNet306.0042F920                                ; |Key = "AUTORUN"
0042F555    . |68 10F94200               push TUNet306.0042F910                                ; |Section = "patch"
0042F55A    . |FF15 25204B00             call dword ptr ds:[<&KERNEL32.GetPrivateProfileIntA>] ; \GetPrivateProfileIntA
取得是否我们在配置文件中的AUTORUN的值,就是看我们的复选框开始时要不要打勾
0042F560    . |5B                        pop ebx
0042F561    . |6A 00                     push 0                                                ; /lParam = 0
0042F563    . |50                        push eax                                              ; |wParam
0042F564    . |68 F1000000               push 0F1                                              ; |Message = BM_SETCHECK
0042F569    . |53                        push ebx                                              ; |hWnd
0042F56A    . |FF15 28044300             call dword ptr ds:[<&USER32.SendMessageA>]            ; \SendMessageA

0042F570    .^ EB 9E                     jmp short TUNet306.0042F510
0042F572      |00                        db 00
0042F573      |00                        db 00
0042F574      |00                        db 00
0042F575      |00                        db 00
0042F576      |00                        db 00
0042F577      |00                        db 00
0042F578      |00                        db 00
0042F579      |00                        db 00
0042F57A      |00                        db 00
0042F57B      |00                        db 00
0042F57C      |00                        db 00
0042F57D      |00                        db 00
0042F57E      |00                        db 00
0042F57F      |00                        db 00
0042F580    > |83EC 50                   sub esp,50
0042F583    . |68 00F94200               push TUNet306.0042F900                                ; /IniFileName = ".\\PEANSEN.ini"
0042F588    . |6A 00                     push 0                                                ; |Default = 0
0042F58A    . |68 20F94200               push TUNet306.0042F920                                ; |Key = "AUTORUN"
0042F58F    . |68 10F94200               push TUNet306.0042F910                                ; |Section = "patch"
0042F594    . |FF15 25204B00             call dword ptr ds:[<&KERNEL32.GetPrivateProfileIntA>] ; \GetPrivateProfileIntA
取得AUTORUN的值开看看要不要在注册表的run项里添加
在这边为了简化处理当要开机自启动时我们在run下的TUNET键值添加文件名
如果不要开机自启动时我们添加0字符串
0042F59A    . |50                        push eax
0042F59B    . |8D4424 04                 lea eax,dword ptr ss:[esp+4]
0042F59F    . |50                        push eax                                              ; /pHandle
0042F5A0    . |68 3F000F00               push 0F003F                                           ; |Access = KEY_ALL_ACCESS
0042F5A5    . |6A 00                     push 0                                                ; |Reserved = 0
0042F5A7    . |68 30F94200               push TUNet306.0042F930                                ; |Subkey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"
0042F5AC    . |68 02000080               push 80000002                                         ; |hKey = HKEY_LOCAL_MACHINE
0042F5B1    . |FF15 08004300             call dword ptr ds:[<&ADVAPI32.RegOpenKeyExA>]         ; \RegOpenKeyExA
0042F5B7    . |83F8 00                   cmp eax,0
0042F5BA    . |0F85 94000000             jnz TUNet306.0042F654
0042F5C0    . |8D4424 08                 lea eax,dword ptr ss:[esp+8]
0042F5C4    . |6A 40                     push 40                                               ; /BufSize = 40 (64.)
0042F5C6    . |50                        push eax                                              ; |PathBuffer
0042F5C7    . |6A 00                     push 0                                                ; |hModule = NULL
0042F5C9    . |FF15 5C024300             call dword ptr ds:[<&KERNEL32.GetModuleFileNameA>]    ; \GetModuleFileNameA
0042F5CF    . |58                        pop eax
0042F5D0    . |83F8 00                   cmp eax,0
0042F5D3    . |74 3E                     je short TUNet306.0042F613
0042F5D5    . |8D0424                    lea eax,dword ptr ss:[esp]
0042F5D8    . |90                        nop
0042F5D9    . |6A 40                     push 40                                               ; /BufSize = 40 (64.)
0042F5DB    . |68 63F94200               push TUNet306.0042F963                                ; |Buffer = TUNet306.0042F963
0042F5E0    . |6A 01                     push 1                                                ; |ValueType = REG_SZ
0042F5E2    . |6A 00                     push 0                                                ; |Reserved = 0
0042F5E4    . |68 68F94200               push TUNet306.0042F968                                ; |ValueName = "TUNET"
0042F5E9    . |FF30                      push dword ptr ds:[eax]                               ; |hKey
0042F5EB    . |FF15 00004300             call dword ptr ds:[<&ADVAPI32.RegSetValueExA>]        ; \RegSetValueExA
0042F5F1    . |68 00F94200               push TUNet306.0042F900                                ; /FileName = ".\\PEANSEN.ini"
0042F5F6    . |68 73F94200               push TUNet306.0042F973                                ; |String = "0"
0042F5FB    . |68 20F94200               push TUNet306.0042F920                                ; |Key = "AUTORUN"
0042F600    . |68 10F94200               push TUNet306.0042F910                                ; |Section = "patch"
0042F605    . |FF15 64014300             call dword ptr ds:[<&KERNEL32.WritePrivateProfileStri>; \WritePrivateProfileStringA
再把启动结果写会配置文件中
0042F60B    . |90                        nop
0042F60C    . |90                        nop
0042F60D    . |90                        nop
0042F60E    . |EB 3A                     jmp short TUNet306.0042F64A
0042F610      |90                        nop
0042F611      |90                        nop
0042F612      |90                        nop
0042F613    > |8D0424                    lea eax,dword ptr ss:[esp]
0042F616    . |90                        nop
0042F617    . |8D5C24 04                 lea ebx,dword ptr ss:[esp+4]
0042F61B    . |6A 50                     push 50                                               ; /BufSize = 50 (80.)
0042F61D    . |53                        push ebx                                              ; |Buffer
0042F61E    . |6A 01                     push 1                                                ; |ValueType = REG_SZ
0042F620    . |6A 00                     push 0                                                ; |Reserved = 0
0042F622    . |68 68F94200               push TUNet306.0042F968                                ; |ValueName = "TUNET"
0042F627    . |FF30                      push dword ptr ds:[eax]                               ; |hKey
0042F629    . |FF15 00004300             call dword ptr ds:[<&ADVAPI32.RegSetValueExA>]        ; \RegSetValueExA
0042F62F    . |90                        nop
0042F630    . |68 00F94200               push TUNet306.0042F900                                ; /FileName = ".\\PEANSEN.ini"
0042F635    . |68 71F94200               push TUNet306.0042F971                                ; |String = "1"
0042F63A    . |68 20F94200               push TUNet306.0042F920                                ; |Key = "AUTORUN"
0042F63F    . |68 10F94200               push TUNet306.0042F910                                ; |Section = "patch"
0042F644    . |FF15 64014300             call dword ptr ds:[<&KERNEL32.WritePrivateProfileStri>; \WritePrivateProfileStringA
0042F64A    > |8B0424                    mov eax,dword ptr ss:[esp]
0042F64D    . |83C4 50                   add esp,50
0042F650    . |EB 0E                     jmp short TUNet306.0042F660
0042F652      |90                        nop
0042F653      |90                        nop
0042F654    > |83C4 54                   add esp,54
0042F657    .^ E9 B4FEFFFF               jmp TUNet306.0042F510
0042F65C      |00                        db 00
0042F65D      |00                        db 00
0042F65E      |00                        db 00
0042F65F      |00                        db 00
0042F660    > |50                        push eax                                              ; /hKey
0042F661    . |FF15 10004300             call dword ptr ds:[<&ADVAPI32.RegCloseKey>]           ; \RegCloseKey
0042F667    .^\E9 A4FEFFFF               jmp TUNet306.0042F510
0042F66C       00                        db 00
0042F66D       00                        db 00
0042F66E       00                        db 00

好了我想odbg也注释的很清楚了。


在看雪中也混了一年了,也没有发过什么帖子,今天就发一个吧
由于我已经大四,考研在即(唉!当初不努力呀)没有更多的时间来学习这里的技术,这篇文章就算是我的一个短暂告别吧。我会回来的,不管我考研的结果怎么样。
呵呵,谢谢这里的各位大虾,小虾。