首页
社区
课程
招聘
[原创]突破封锁线:第四章--代码篇
发表于: 2006-5-13 21:27 19591

[原创]突破封锁线:第四章--代码篇

2006-5-13 21:27
19591

【文章标题】: 突破封锁线:第四章--代码篇
【文章作者】: Austin
【作者邮箱】: austiny.cn@gmail.com
【软件名称】: 神州数码网络客户登陆程序
【软件大小】: 不重要
【下载地址】: 自己搜索下载
【加壳方式】: UltraProtect 1.x
【保护方式】: 加壳 网络封禁
【编写语言】: VC6.0
【使用工具】: OllyDbg VC6.0 LordPE
【操作平台】: Windows2003
【软件介绍】: 神州数码小区宽带网络登陆客户端,诸多限制
【作者声明】: 技术交流中。。。
--------------------------------------------------------------------------------
【详细过程】
  一、(停电)蜡烛 + 收音机 = 前情回顾
  
  上一回说到,我们找到了DIGI的弱点,我们来突破它。。。
  
  二、(热身)第一次的亲密接触
  
  我们的计划是,截获DIGI发包的函数,用我们自己的发包函数来替代它发出伪造过的包。
  (据说在欧洲,穿假名牌是要脱光光的。[口水],真是好制度啊)
  
  用OllyDbg打开DIGI,停在入口处:
  
  0040FB74 >/$  68 A82A4100   push    00412AA8
  0040FB79  |.  68 D4FC4000   push    <jmp.&msvcrt._except_handler3>   ;  SE 处理程序安装
  0040FB7E  |.  64:A1 0000000>mov     eax, fs:[0]
  
  网络应用程序发送数据包,最后都要用到wsock32.dll中的sendto函数。找到这个函数,就能找到调用它的发包函数。
  
  在CPU窗口中点击Ctrl+N查看当前模块中的名称,果然发现了对sendto函数的引用:
  
  ...
  00411538   .rdata     输入    (    user32.SendMessageA
  00411598   .rdata     输入    (    wsock32.sendto
  00411064   .rdata     输入    (    kernel32.SetEvent
  ...
  
  光标移到sendto项上,回车查看输入函数参考:
  
  参考位于 digi_dum:.text 到 wsock32.sendto
  地址       反汇编                                    注释
  00403A10   call    <jmp.&wsock32.sendto>
  00403A31   call    <jmp.&wsock32.sendto>
  00403A52   call    <jmp.&wsock32.sendto>
  00403A73   call    <jmp.&wsock32.sendto>
  00403CC3   call    <jmp.&wsock32.sendto>
  00403CE8   call    <jmp.&wsock32.sendto>
  00403D07   call    <jmp.&wsock32.sendto>
  00403ECF   call    <jmp.&wsock32.sendto>
  004040F9   call    <jmp.&wsock32.sendto>
  0040542F   call    <jmp.&wsock32.sendto>
  004083F4   call    <jmp.&wsock32.sendto>
  0040FD50   jmp     [<&wsock32.sendto>]               WS2_32.sendto
  
  出去最后一项是一个跳转,我们来挨个考察到底哪个调用是发包函数:
  
  在第一项上回车,在cpu窗口中来到00403A10处:
  
  004039FF   .  8BF0          mov     esi, eax
  00403A01   .  8D4424 24     lea     eax, [esp+24]
  00403A05   .  6A 10         push    10                               ; /ToLength = 10 (16.)
  00403A07   .  50            push    eax                              ; |pTo
  00403A08   .  55            push    ebp                              ; |Flags
  00403A09   .  8D4C24 40     lea     ecx, [esp+40]                    ; |
  00403A0D   .  56            push    esi                              ; |DataSize
  00403A0E   .  51            push    ecx                              ; |Data
  00403A0F   .  52            push    edx                              ; |Socket => 0
  00403A10   .  E8 3BC30000   call    <jmp.&wsock32.sendto>            ; \sendto
  00403A15   .  68 4A010000   push    14A
  00403A1A   .  FFD3          call    ebx
  00403A1C   .  8B15 386C4100 mov     edx, [416C38]
  00403A22   .  8D4424 24     lea     eax, [esp+24]
  00403A26   .  6A 10         push    10                               ; /ToLength = 10 (16.)
  00403A28   .  50            push    eax                              ; |pTo
  00403A29   .  55            push    ebp                              ; |Flags
  00403A2A   .  8D4C24 40     lea     ecx, [esp+40]                    ; |
  00403A2E   .  56            push    esi                              ; |DataSize
  00403A2F   .  51            push    ecx                              ; |Data
  00403A30   .  52            push    edx                              ; |Socket => 0
  00403A31   .  E8 1AC30000   call    <jmp.&wsock32.sendto>            ; \sendto
  00403A36   .  68 4A010000   push    14A
  00403A3B   .  FFD3          call    ebx
  00403A3D   .  8B15 386C4100 mov     edx, [416C38]
  00403A43   .  8D4424 24     lea     eax, [esp+24]
  00403A47   .  6A 10         push    10                               ; /ToLength = 10 (16.)
  00403A49   .  50            push    eax                              ; |pTo
  00403A4A   .  55            push    ebp                              ; |Flags
  00403A4B   .  8D4C24 40     lea     ecx, [esp+40]                    ; |
  00403A4F   .  56            push    esi                              ; |DataSize
  00403A50   .  51            push    ecx                              ; |Data
  00403A51   .  52            push    edx                              ; |Socket => 0
  00403A52   .  E8 F9C20000   call    <jmp.&wsock32.sendto>            ; \sendto
  00403A57   .  68 4A010000   push    14A
  00403A5C   .  FFD3          call    ebx
  00403A5E   .  8B15 386C4100 mov     edx, [416C38]
  00403A64   .  8D4424 24     lea     eax, [esp+24]
  00403A68   .  6A 10         push    10                               ; /ToLength = 10 (16.)
  00403A6A   .  50            push    eax                              ; |pTo
  00403A6B   .  55            push    ebp                              ; |Flags
  00403A6C   .  8D4C24 40     lea     ecx, [esp+40]                    ; |
  00403A70   .  56            push    esi                              ; |DataSize
  00403A71   .  51            push    ecx                              ; |Data
  00403A72   .  52            push    edx                              ; |Socket => 0
  00403A73   .  E8 D8C20000   call    <jmp.&wsock32.sendto>            ; \sendto
  00403A78   .  A1 386C4100   mov     eax, [416C38]
  00403A7D   .  5F            pop     edi
  00403A7E   .  3BC5          cmp     eax, ebp
  00403A80   .  74 0C         je      short 00403A8E
  00403A82   .  50            push    eax                              ; /Socket => 0
  00403A83   .  E8 C2C20000   call    <jmp.&wsock32.closesocket>       ; \closesocket
  
  一眼扫去,不免多看了几行,发现这里有连续四次对sendto的调用,也就是说连续发出了四个数据包。
  回忆一下上一章的内容,。。。,对了,只有在断开连接的时候才会发出4个包的,所以前4个调用都可以排除。
  
  看看第5个,00403CC3:
  
  00403CB5  |.  8BF0          mov     esi, eax
  00403CB7  |.  6A 10         push    10                               ; /ToLength = 10 (16.)
  00403CB9  |.  52            push    edx                              ; |pTo
  00403CBA  |.  6A 00         push    0                                ; |Flags = 0
  00403CBC  |.  8D4424 34     lea     eax, [esp+34]                    ; |
  00403CC0  |.  56            push    esi                              ; |DataSize
  00403CC1  |.  50            push    eax                              ; |Data
  00403CC2  |.  51            push    ecx                              ; |Socket => 0
  00403CC3  |.  E8 88C00000   call    <jmp.&wsock32.sendto>            ; \sendto
  00403CC8  |.  8B3D 7C104100 mov     edi, [<&kernel32.Sleep>]         ;  kernel32.Sleep
  00403CCE  |.  6A 64         push    64                               ; /Timeout = 100. ms
  00403CD0  |.  FFD7          call    edi                              ; \Sleep
  00403CD2  |.  8B0D 386C4100 mov     ecx, [416C38]
  00403CD8  |.  8D5424 18     lea     edx, [esp+18]
  00403CDC  |.  6A 10         push    10                               ; /ToLength = 10 (16.)
  00403CDE  |.  52            push    edx                              ; |pTo
  00403CDF  |.  6A 00         push    0                                ; |Flags = 0
  00403CE1  |.  8D4424 34     lea     eax, [esp+34]                    ; |
  00403CE5  |.  56            push    esi                              ; |DataSize
  00403CE6  |.  50            push    eax                              ; |Data
  00403CE7  |.  51            push    ecx                              ; |Socket => 0
  00403CE8  |.  E8 63C00000   call    <jmp.&wsock32.sendto>            ; \sendto
  00403CED  |.  6A 64         push    64                               ; /Timeout = 100. ms
  00403CEF  |.  FFD7          call    edi                              ; \Sleep
  00403CF1  |.  8B0D 386C4100 mov     ecx, [416C38]
  00403CF7  |.  8D5424 18     lea     edx, [esp+18]
  00403CFB  |.  6A 10         push    10                               ; /ToLength = 10 (16.)
  00403CFD  |.  52            push    edx                              ; |pTo
  00403CFE  |.  6A 00         push    0                                ; |Flags = 0
  00403D00  |.  8D4424 34     lea     eax, [esp+34]                    ; |
  00403D04  |.  56            push    esi                              ; |DataSize
  00403D05  |.  50            push    eax                              ; |Data
  00403D06  |.  51            push    ecx                              ; |Socket => 0
  00403D07  |.  E8 44C00000   call    <jmp.&wsock32.sendto>            ; \sendto
  00403D0C  |.  5F            pop     edi
  00403D0D  |.  B8 01000000   mov     eax, 1
  00403D12  |.  5E            pop     esi
  00403D13  |.  81C4 20020000 add     esp, 220
  00403D19  \.  C3            retn
  
  习惯性的又多看了几行,这里发了三个包,中间用Sleep函数作了0.1秒的技术暂停。
  (理发师:很明显我就是这样的人)
  (包租公包租婆:很明显,你不是)
  
  既然不是,又排除三个,我们再往下看,00403ECF:
  
  00403EB1   .  BF 01000000   mov     edi, 1
  00403EB6   .  52            push    edx                              ; /ToLength
  00403EB7   .  8D5424 40     lea     edx, [esp+40]                    ; |
  00403EBB   .  52            push    edx                              ; |pTo
  00403EBC   .  53            push    ebx                              ; |Flags
  00403EBD   .  50            push    eax                              ; |DataSize
  00403EBE   .  8D8424 700100>lea     eax, [esp+170]                   ; |
  00403EC5   .  50            push    eax                              ; |Data
  00403EC6   .  51            push    ecx                              ; |Socket => 0
  00403EC7   .  894C24 78     mov     [esp+78], ecx                    ; |
  00403ECB   .  897C24 74     mov     [esp+74], edi                    ; |
  00403ECF   .  E8 7CBE0000   call    <jmp.&wsock32.sendto>            ; \sendto
  00403ED4   .  A1 386C4100   mov     eax, [416C38]
  00403ED9   .  8D4C24 34     lea     ecx, [esp+34]
  00403EDD   .  51            push    ecx                              ; /pTimeout
  00403EDE   .  53            push    ebx                              ; |Exceptfds
  00403EDF   .  8D5424 64     lea     edx, [esp+64]                    ; |
  00403EE3   .  53            push    ebx                              ; |Writefds
  00403EE4   .  40            inc     eax                              ; |
  00403EE5   .  52            push    edx                              ; |Readfds
  00403EE6   .  50            push    eax                              ; |nfds
  00403EE7   .  E8 7CBE0000   call    <jmp.&wsock32.select>            ; \select
  00403EEC   .  83F8 FF       cmp     eax, -1
  00403EEF   .  74 65         je      short 00403F56
  00403EF1   .  8B15 386C4100 mov     edx, [416C38]
  00403EF7   .  8D4C24 5C     lea     ecx, [esp+5C]
  00403EFB   .  51            push    ecx
  00403EFC   .  52            push    edx
  00403EFD   .  E8 60BE0000   call    <jmp.&wsock32.__WSAFDIsSet>
  00403F02   .  85C0          test    eax, eax
  00403F04   .  74 50         je      short 00403F56
  00403F06   .  8D4424 14     lea     eax, [esp+14]
  00403F0A   .  8D4C24 4C     lea     ecx, [esp+4C]
  00403F0E   .  50            push    eax                              ; /pFromLen
  00403F0F   .  A1 386C4100   mov     eax, [416C38]                    ; |
  00403F14   .  51            push    ecx                              ; |pFrom
  00403F15   .  53            push    ebx                              ; |Flags
  00403F16   .  8D9424 6C0300>lea     edx, [esp+36C]                   ; |
  00403F1D   .  68 00020000   push    200                              ; |BufSize = 200 (512.)
  00403F22   .  52            push    edx                              ; |Buffer
  00403F23   .  50            push    eax                              ; |Socket => 0
  00403F24   .  E8 33BE0000   call    <jmp.&wsock32.recvfrom>          ; \recvfrom
  00403F29   .  8BF0          mov     esi, eax
  
  这个很完整了,call完sendto,又call了select和recvfrom,有嫌疑。
  (靠,call这么多人来,斧头帮聚会啊)
  
  先不着急,再看下一个,004040F9:
  
  004040DA   .  BF 01000000   mov     edi, 1
  004040DF   .  52            push    edx                              ; /ToLength
  004040E0   .  8D5424 40     lea     edx, [esp+40]                    ; |
  004040E4   .  52            push    edx                              ; |pTo
  004040E5   .  6A 00         push    0                                ; |Flags = 0
  004040E7   .  50            push    eax                              ; |DataSize
  004040E8   .  8D8424 700100>lea     eax, [esp+170]                   ; |
  004040EF   .  50            push    eax                              ; |Data
  004040F0   .  51            push    ecx                              ; |Socket => 0
  004040F1   .  894C24 78     mov     [esp+78], ecx                    ; |
  004040F5   .  897C24 74     mov     [esp+74], edi                    ; |
  004040F9   .  E8 52BC0000   call    <jmp.&wsock32.sendto>            ; \sendto
  004040FE   .  A1 386C4100   mov     eax, [416C38]
  00404103   .  8D4C24 2C     lea     ecx, [esp+2C]
  00404107   .  51            push    ecx                              ; /pTimeout
  00404108   .  6A 00         push    0                                ; |Exceptfds = NULL
  0040410A   .  8D5424 64     lea     edx, [esp+64]                    ; |
  0040410E   .  6A 00         push    0                                ; |Writefds = NULL
  00404110   .  40            inc     eax                              ; |
  00404111   .  52            push    edx                              ; |Readfds
  00404112   .  50            push    eax                              ; |nfds
  00404113   .  E8 50BC0000   call    <jmp.&wsock32.select>            ; \select
  00404118   .  3BC7          cmp     eax, edi
  0040411A   .  75 78         jnz     short 00404194
  0040411C   .  8B15 386C4100 mov     edx, [416C38]
  00404122   .  8D4C24 5C     lea     ecx, [esp+5C]
  00404126   .  51            push    ecx
  00404127   .  52            push    edx
  00404128   .  E8 35BC0000   call    <jmp.&wsock32.__WSAFDIsSet>
  0040412D   .  85C0          test    eax, eax
  0040412F   .  74 68         je      short 00404199
  00404131   .  8D4424 14     lea     eax, [esp+14]
  00404135   .  8D4C24 4C     lea     ecx, [esp+4C]
  00404139   .  50            push    eax                              ; /pFromLen
  0040413A   .  A1 386C4100   mov     eax, [416C38]                    ; |
  0040413F   .  51            push    ecx                              ; |pFrom
  00404140   .  6A 00         push    0                                ; |Flags = 0
  00404142   .  8D9424 6C0300>lea     edx, [esp+36C]                   ; |
  00404149   .  68 00020000   push    200                              ; |BufSize = 200 (512.)
  0040414E   .  52            push    edx                              ; |Buffer
  0040414F   .  50            push    eax                              ; |Socket => 0
  00404150   .  E8 07BC0000   call    <jmp.&wsock32.recvfrom>          ; \recvfrom
  00404155   .  8BF0          mov     esi, eax
  00404157   .  85F6          test    esi, esi
  00404159   .  7E 2C         jle     short 00404187
  0040415B   .  8B0D A86E4100 mov     ecx, [416EA8]
  00404161   .  51            push    ecx                              ; /pAddr => 00034460
  00404162   .  E8 EFBB0000   call    <jmp.&wsock32.inet_addr>         ; \inet_addr
  00404167   .  394424 50     cmp     [esp+50], eax
  0040416B   .  75 1A         jnz     short 00404187
  0040416D   .  8D9424 600300>lea     edx, [esp+360]
  00404174   .  56            push    esi
  00404175   .  52            push    edx
  00404176   .  E8 651A0000   call    00405BE0
  0040417B   .  8BE8          mov     ebp, eax
  0040417D   .  83C4 08       add     esp, 8
  00404180   .  83FD 02       cmp     ebp, 2
  00404183   .  74 73         je      short 004041F8
  00404185   .  EB 12         jmp     short 00404199
  00404187   >  68 88130000   push    1388                             ; /Timeout = 5000. ms
  0040418C   .  FF15 7C104100 call    [<&kernel32.Sleep>]              ; \Sleep
  00404192   .  EB 05         jmp     short 00404199
  00404194   >  BD 21000000   mov     ebp, 21
  00404199   >  43            inc     ebx
  0040419A   .  3BEF          cmp     ebp, edi
  0040419C   .  75 0D         jnz     short 004041AB
  0040419E   .  68 30750000   push    7530                             ; /Timeout = 30000. ms
  004041A3   .  33DB          xor     ebx, ebx                         ; |
  004041A5   .  FF15 7C104100 call    [<&kernel32.Sleep>]              ; \Sleep
  004041AB   >  393D 6C6E4100 cmp     [416E6C], edi
  004041B1   .^ 0F84 D3FEFFFF je      0040408A
  004041B7   .  EB 72         jmp     short 0040422B
  004041B9   >  A1 386C4100   mov     eax, [416C38]
  004041BE   .  33F6          xor     esi, esi
  004041C0   .  50            push    eax                              ; /Socket => 0
  004041C1   .  8935 6C6E4100 mov     [416E6C], esi                    ; |
  004041C7   .  E8 7EBB0000   call    <jmp.&wsock32.closesocket>       ; \closesocket
  004041CC   .  8935 386C4100 mov     [416C38], esi
  004041D2   .  E8 6DBB0000   call    <jmp.&wsock32.WSACleanup>        ; [WSACleanup
  004041D7   .  56            push    esi
  
  (这个call不但完整,而且小小年纪竟然就有一副横练的筋骨,真是百年难得一遇的武学奇才。)
  注意到有一个30秒的sleep,回忆上一章的内容,没错,每隔三十秒发包,这个就是用来保持连接的。
  
  考虑到上一个嫌疑调用就在这儿不远处,极有可能就是发包函数。
  
  在斧头帮聚会的00403ECF处,下一个断点,跑起来。
  
  然后连接,果然,程序乖乖的断在了00403ECF处。就是这里啦。(记下来)
  
  当然,给sendto的调用下全局断点,然后运行看停在哪里,也是一样的。只是--
  (只是,只是我当时没有想到而已。有时觉得自己真是聪明的可以)
  
  三、(再热)第二次的亲密接触
  
  (如果把整个太平洋的水倒出来。。。 再热的话,太平洋里就没有水了)
  
  还记得整容的时候给DIGI加的"高级"按钮吗?现在我们来给它加上处理函数。
  
  由于DIGI是一个MFC程序,所以突破口在CCmdTarget::OnCmdMsg(此函数是mfc对windows消息处理的封装)
  
  先找到主对话框的消息表:
  
  重新加载DIGI,Ctrl+N打开名称列表,找到CCmdTarget::OnCmdMsg:
  
  ...
  00411374   .rdata     输入         mfc42.#4407_CWnd::OnChildNotify
  00411138   .rdata     输入         mfc42.#4424_CCmdTarget::OnCmdMsg
  ...
  
  在数据窗口跟随至 00411138:
  
  00411138 >6BC4223C  mfc42.#4424_CCmdTarget::OnCmdMsg
  0041113C >6BCB87C6  mfc42.#3738_CWinApp::GetRuntimeClass
  00411140 >6BC575A1  mfc42.#815_CWinApp::~CWinApp
  00411144 >6BC4AFAF  mfc42.#561_CWinApp::CWinApp
  00411148 >6BC48D34  mfc42.#641_CDialog::~CDialog
  0041114C >6BC5019D  mfc42.#609_CButton::~CButton
  00411150 >6BC544E5  mfc42.#795_CStatic::~CStatic
  00411154 >6BC56AB1  mfc42.#2514_CDialog::DoModal
  
  可知CCmdTarget::OnCmdMsg的地址在6BC4223C,在6BC4223C处下断,点击界面中高级按钮,断点如约而至:
  
  6BC4223C >  55              push    ebp
  6BC4223D    8BEC            mov     ebp, esp
  6BC4223F    8B45 0C         mov     eax, [ebp+C]
  6BC42242    53              push    ebx
  6BC42243    56              push    esi
  6BC42244    57              push    edi
  6BC42245    83F8 FE         cmp     eax, -2
  6BC42248    8BF9            mov     edi, ecx
  6BC4224A    0F84 21C30500   je      6BC9E571
  6BC42250    83F8 FD         cmp     eax, -3
  6BC42253    0F84 39C30500   je      6BC9E592
  6BC42259    83F8 FF         cmp     eax, -1
  6BC4225C    75 29           jnz     short 6BC42287
  6BC4225E    BB 11010000     mov     ebx, 111
  6BC42263    8B07            mov     eax, [edi]
  6BC42265    8BCF            mov     ecx, edi
  6BC42267    FF50 30         call    [eax+30]
  6BC4226A    8BF0            mov     esi, eax
  6BC4226C    85F6            test    esi, esi
  6BC4226E    74 40           je      short 6BC422B0
  6BC42270    FF75 08         push    dword ptr [ebp+8]
  6BC42273    FF75 0C         push    dword ptr [ebp+C]
  6BC42276    53              push    ebx
  6BC42277    FF76 04         push    dword ptr [esi+4]
  6BC4227A    E8 09FEFFFF     call    #1145_AfxFindMessageEntry
  
  将光标停至 6BC4227A    E8 09FEFFFF     call    #1145_AfxFindMessageEntry 这句,
  F4运行到此处,前一句 6BC42277    FF76 04         push    dword ptr [esi+4] 压入栈中的就指向消息映射表的地址。
  
  看看堆栈:
  
  0012EBF8   00411814  digi.00411814
  0012EBFC   00000111
  0012EC00   FFFFFFFF
  0012EC04   0000800B
  0012EC08   FFFFFFFF
  
  可知我们要找的消息表地址就在00411814里,在数据窗口中跟随(地址显示方式):
  
  00411814  00411818  digi.00411818
  
  注意00411814指向的00411818即为消息表,内容如下:
  
  00411818  00000112  <-- 消息号
  0041181C  00000000  <-- Code
  00411820  00000000  <-- 控件ID
  00411824  00000000  <-- 最后一个空间ID
  00411828  00000012  <-- 响应函数类型
  0041182C  00402730  digi.00402730  <-- 响应函数
  00411830  0000000F
  00411834  00000000
  ...
  00411A4C  00000000
  00411A50  0000000D
  00411A54  00404E90  digi.00404E90  <-- 消息表结束于此
  00411A58  00000000
  00411A5C  00000000
  00411A60  00000000
  00411A64  00000000
  00411A68  00000000
  00411A6C  00000000
  00411A70  0040F612  <jmp.&mfc42.#3597_CDialog::GetRuntimeClass>
  
  要处理我们自己的按钮消息,要在表中加入新项,注意到表结束后紧跟其他数据,故没有足够的空间来加入新项。
  没关系,我们将消息处理表整个移到别处。
  
  回忆一下Digi整容的成果:
  
                   地址          长度
       .text       00410000     10000
       .rdata      00411000      4000
       .data       00415000    204000
       .oldrsrc    00619000      3000
       .perplex    0061C000     1D000
       .newimt     00639000      1000
       .rsrc       0063A000      3000
  
  对了,.perplex是壳代码所在的段,现在正好用来放我们要加入的东西。
  
  在数据窗口中选中从 00411818 到 00411A54 的所有内容,然后选择二进制复制。
  
  将00411814的内容改为 0061C518,这就是新消息表的地址。
  在数据窗口中右键,选择复制到可执行文件,保存下来。
  
  在数据窗口中来到0061C518处,选择二进制粘贴。
  来到消息表的末尾0061C784处:
  
  0061C778  00000000
  0061C77C  00000000
  0061C780  0000000C
  0061C784  0061CD06  digi.0061CD06
  
  从0061C758开始填充自己的消息:
  
  0061C758  00000111 <-- 0x111消息,WM_COMMAND
  0061C75C  00000000
  0061C760  000003ED <-- 3ED即我们加入的"高级"按钮的资源ID
  0061C764  000003ED
  0061C768  0000000C
  0061C76C  00000000 <-- 此处应为响应函数地址,先留空
  0061C770  00000110 <-- 0x110消息,WM_INITDIALOG
  0061C774  00000000
  0061C778  00000000
  0061C77C  00000000
  0061C780  0000000C
  0061C784  0061CD06  digi.0061CD06 <-- 我们的窗体初始化消息响应写在此处
  0061C788  00000111  <-- 0x111消息,WM_COMMAND
  0061C78C  00000000
  0061C790  0000800B  <-- 800B为我们加入的"高级"菜单项的资源ID
  0061C794  0000800B
  0061C798  0000000C
  0061C79C  00000000  <-- 响应函数,留空
  0061C7A0  00000000
  0061C7A4  00000000
  0061C7A8  00000000
  0061C7AC  00000000
  0061C7B0  00000000
  0061C7B4  00000000
  
  选中从0061C518到0061C7B4,复制到可执行文件,保存。
  
  四、(脱水)第三类接触
  
  (热到脱水的时候,轻舞飞扬也会变成外星人。注:美女就是美女,永远也变不成恐龙。反之亦然)
  
  下面我们来加入一个窗体初始化处理函数,来完成Digi主窗口初始化的时候,加载我们自己的dll和取得函数地址。
  
  在代码窗口中来到0061CD06处,开始写汇编代码:
  
  0061CD07    68 10CC6100     push    0061CC10                                   ; ASCII "dycdll.dll"
  0061CD0C    E8 4F511E7C     call    kernel32.LoadLibraryA
  0061CD11    50              push    eax
  0061CD12    68 20CC6100     push    0061CC20                                   ; ASCII "_Mysendto@24"
  0061CD17    50              push    eax
  0061CD18    E8 A4F2207C     call    kernel32.GetProcAddress
  0061CD1D    BB 40CC6100     mov     ebx, 0061CC40
  0061CD22    8903            mov     [ebx], eax
  0061CD24    58              pop     eax
  0061CD25    50              push    eax
  0061CD26    68 30CC6100     push    0061CC30                                   ; ASCII "Mysetting"
  0061CD2B    50              push    eax
  0061CD2C    E8 90F2207C     call    kernel32.GetProcAddress
  0061CD31    BB 6CC76100     mov     ebx, 0061C76C
  0061CD36    8903            mov     [ebx], eax
  0061CD38    BB 9CC76100     mov     ebx, 0061C79C
  0061CD3D    8903            mov     [ebx], eax
  0061CD3F    58              pop     eax
  0061CD40    50              push    eax
  0061CD41    68 60CC6100     push    0061CC60                                   ; ASCII "Getnotest"
  0061CD46    50              push    eax
  0061CD47    E8 75F2207C     call    kernel32.GetProcAddress
  0061CD4C    BB 50CC6100     mov     ebx, 0061CC50
  0061CD51    8903            mov     [ebx], eax
  0061CD53    58              pop     eax
  0061CD54    90              nop
  0061CD55    90              nop
  0061CD56    90              nop
  0061CD57    61              popad
  0061CD58  - E9 5354DEFF     jmp     004021B0                              ;跳回到原处理函数
  
  其中用到的变量有:
  
  0061CC10 - dll文件名
  0061CC20 - 我们的sendto函数名
  0061CC30 - 我们的按钮处理函数名
  0061CC40 - 保存sendto函数地址
  0061CC50 - 保存Getnotest函数地址
  0061CC60 - 我们的Getnotest函数名
  
  0061CC10  dycdll.dll......_Mysendto@24....
  0061CC30  Mysetting.......?.............
  0061CC50  P.............Getnotest.......
  
  注意到按钮处理函数的地址已经被写到0061C76C和0061C79C的消息表项中。
  
  将汇编和变量的修改复制到可执行文件,保存。
  (和所有的动作游戏一样,请养成随时存档的习惯)
  
  五、(晕了)真的晕了
  
  (欢迎来到代码篇)
  
  下面我们来修改登陆时调用的sendto函数,来到00403ECF处:
  00403ECF   .  E8 7CBE0000   call    <jmp.&wsock32.sendto>            ; \sendto
  
  修改为
  00403ECF    E8 E88D2100     call    0061CCCB   ; 0061CCCB为我们自己的处理函数
  
  复制到可执行文件,保存。
  
  来到 0061CCCB处,开始汇编:
  
  0061CCCB    A1 40CC6100     mov     eax, [61CC40]                             ;其中有我们的sendto函数地址
  0061CCD0    83F8 00         cmp     eax, 0
  0061CCD3    74 0B           je      short 0061CCE0
  0061CCD5    90              nop
  0061CCD6    90              nop
  0061CCD7    90              nop
  0061CCD8  - FF25 40CC6100   jmp     [61CC40]                                   ; dycdll.Mysendto
  0061CCDE    90              nop
  0061CCDF    90              nop
  0061CCE0  - E9 D4AA5471     jmp     WS2_32.sendto
  
  完成的功能就是如果我们自己的sendto函数已经加载,就用我们的sendto函数工作,否则用系统的sendto函数工作。
  
  复制到可执行文件,保存。
  
  (喝口水,成功在即了)
  
  六、(编程)如果上帝是个程序员
  
  脏活累活干得差不多了,写点优雅的代码吧。
  
  打开VC6.0,新建一个MFC的DLL工程。
  
  加入如下变量和函数定义。
  
  //下列变量保存sendto发出的包内容
  int len_authorize=0;
  int flags_authorize=0;
  struct sockaddr to_authorize={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  char buf_authorize[100]={0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0
  };
  int tolen_authorize=0;
  
  //这三个变量保存程序运行方式
  BOOL NoTest=TRUE;     //是否禁止代理检测等
  BOOL SAVE=FALSE;      //是否保存登陆包
  BOOL LOAD=FALSE;      //是否调入保存的登陆包(路由器穿透时用)
  
  void ReadIni()        //读配置文件
  {
          NoTest=GetPrivateProfileInt("Setting","NoTest",1,".\\dyc.ini");
          SAVE=GetPrivateProfileInt("Setting","SAVE",0,".\\dyc.ini");
          LOAD=GetPrivateProfileInt("Setting","LOAD",0,".\\dyc.ini");
  }
  
  void WriteIni()       //写配置文件
  {
          CString tmp;
          tmp.Format("%d",NoTest);
          WritePrivateProfileString("Setting","NoTest",tmp,".\\dyc.ini");
          tmp.Format("%d",SAVE);
          WritePrivateProfileString("Setting","SAVE",tmp,".\\dyc.ini");
          tmp.Format("%d",LOAD);
          WritePrivateProfileString("Setting","LOAD",tmp,".\\dyc.ini");
  }
  
  void Load()           //调入保存的包
  {
          HANDLE t=CreateFile("auth.dat",GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,NULL,NULL);
          if(t != INVALID_HANDLE_VALUE)
          {
                  unsigned long xlen;
  
                  ReadFile(t,&len_authorize,1,&xlen,NULL);
                  ReadFile(t,&flags_authorize,1,&xlen,NULL);
                  ReadFile(t,&to_authorize,15,&xlen,NULL);
                  ReadFile(t,&buf_authorize,100,&xlen,NULL);
                  ReadFile(t,&tolen_authorize,1,&xlen,NULL);
  
                  CloseHandle(t);
          }
  
  }
  
  void Save()           //保存包
  {
          HANDLE t=CreateFile("auth.dat",GENERIC_WRITE,FILE_SHARE_WRITE,NULL,CREATE_ALWAYS,NULL,NULL);
          if(t != INVALID_HANDLE_VALUE)
          {
                  unsigned long xlen;
                  WriteFile(t,&len_authorize,1,&xlen,NULL);
                  WriteFile(t,&flags_authorize,1,&xlen,NULL);
                  WriteFile(t,&to_authorize,15,&xlen,NULL);
                  WriteFile(t,&buf_authorize,100,&xlen,NULL);
                  WriteFile(t,&tolen_authorize,1,&xlen,NULL);
  
                  CloseHandle(t);
                  }
  }
  
  extern "C" __declspec(dllexport) BOOL Getnotest()    //导出函数,得到是否不检测
  {
          return NoTest;
  }
  
  extern "C" __declspec(dllexport) void Mysetting()    //导出函数,"高级"按钮处理函数,显示一个对话框
  {
          AFX_MANAGE_STATE(AfxGetStaticModuleState());
          CAdForm p;
          p.DoModal();
  //        MessageBox(NULL,"Ha","ha",MB_OK);
  }
  
  extern "C" __declspec(dllexport) int WINAPI Mysendto(  //导出函数,我们自己的sendto函数
    SOCKET s,                        
    const char FAR * buf,            
    int len,                        
    int flags,                       
    const struct sockaddr FAR * to,  
    int tolen                        
  )
  {
          int result;
  
          for(int tt=0;tt<len;tt++)
          {
                  *(buf_authorize+tt)=*(buf+tt);
          }
          len_authorize=len;
          tolen_authorize=tolen;
          flags_authorize=flags;
          strcpy(to_authorize.sa_data,to->sa_data);
          to_authorize.sa_family=to->sa_family;
         
          if(SAVE)Save();
          if(LOAD)Load();
  
          result=::sendto(s,buf_authorize,len_authorize,flags_authorize,&to_authorize,tolen_authorize);
          return result;
  }
  
  然后加入一个对话框,在其中处理对程序工作的设置等。
  
  编译得到的dll文件就可以使用了。
  通过自己的sendto函数,我们可以截获正常情况下的登陆数据包,然后在路由器后使用,就可以穿透路由器,正常登陆了。
  
  七、(点歌)我点一首歌,不要对唱的
  
  下面我们来解决最后一个检测代理和BT的问题。
  
  先看看登陆代码:
  
  0040402C   .  8B15 4C8D6100 mov     edx, [618D4C]
  00404032   .  893D 6C6E4100 mov     [416E6C], edi
  00404038   .  891D 706E4100 mov     [416E70], ebx
  0040403E   .  53            push    ebx                                     ; /lParam
  0040403F   .  8B82 70030400 mov     eax, [edx+40370]                        ; |
  00404045   .  66:C705 026F4>mov     word ptr [416F02], 3                    ; |
  0040404E   .  A3 746F4100   mov     [416F74], eax                           ; |
  00404053   .  8B4D 20       mov     ecx, [ebp+20]                           ; |
  00404056   .  57            push    edi                                     ; |wParam
  00404057   .  68 8C040000   push    48C                                     ; |Message = MSG(48C)
  0040405C   .  51            push    ecx                                     ; |hWnd
  0040405D   .  FF15 24154100 call    [<&user32.PostMessageA>]                ; \PostMessageA
  00404063   >  A1 506C4100   mov     eax, [416C50]
  
  登陆成功后一直执行到0040405D出会有一个对PostMessageA的调用,发送窗口消息,消息代码是48C。
  初步估计这个消息的响应函数中会有检测的代码。(后来我们才知道,要相信男人的直觉)
  
  来到消息表0061c518,往下看直到:
  
  0061C660  0000000A
  0061C664  00404250  digi_new.00404250
  0061C668  0000048C  <-- 就是我们要找的48C
  0061C66C  00000000
  0061C670  00000000
  0061C674  00000000
  0061C678  0000000A
  0061C67C  00403AC0  digi_new.00403AC0  <-- 这个就是消息响应函数了
  0061C680  00000485
  
  不多说,在代码窗口中跟到00403AC0:
  
  00403AC0   .  64:A1 0000000>mov     eax, fs:[0]
  00403AC6   .  6A FF         push    -1
  00403AC8   .  68 30024100   push    00410230
  00403ACD   .  50            push    eax
  00403ACE   .  64:8925 00000>mov     fs:[0], esp
  00403AD5   .  83EC 64       sub     esp, 64
  00403AD8   .  66:C705 026F4>mov     word ptr [416F02], 3
  00403AE1   .  C705 DC6E4100>mov     dword ptr [416EDC], 1
  00403AEB   .  6A 00         push    0
  00403AED   .  6A 00         push    0
  00403AEF   .  6A 00         push    0
  00403AF1   .  6A 00         push    0
  00403AF3   .  51            push    ecx
  00403AF4   .  68 109C4000   push    00409C10
  00403AF9   .  E8 E0BB0000   call    <jmp.&mfc42.#1105_AfxBeginThread>
  00403AFE   .  A1 306E4100   mov     eax, [416E30]
  00403B03   .  8B48 F8       mov     ecx, [eax-8]
  00403B06   .  85C9          test    ecx, ecx
  ...
  00403B56   .  C2 0800       retn    8
  
  注意到00403AF9处的AfxBeginThread函数启动了一个线程,线程函数地址为00409C10,跟进去。
  
  00409C10   .  6A FF         push    -1
  00409C12   .  68 4C094100   push    0041094C                                ;  SE 处理程序安装
  00409C17   .  64:A1 0000000>mov     eax, fs:[0]
  00409C1D   .  50            push    eax
  00409C1E   .  64:8925 00000>mov     fs:[0], esp
  ...
  00409CC6   .  A3 606F4100   mov     [416F60], eax
  00409CCB   .  E8 A0150000   call    0040B270            ;<-- 有call,跟进去发现很短,不是
  00409CD0   .  83C4 04       add     esp, 4
  00409CD3   .  8BF0          mov     esi, eax
  00409CD5   .  E8 264B0000   call    0040E800            ;<-- 又有,跟进去也不是,再往下看
  00409CDA   .  2B05 44704100 sub     eax, [417044]
  ...
  00409D8D   .  8D5424 30     lea     edx, [esp+30]
  00409D91   .  891D 346E4100 mov     [416E34], ebx
  00409D97   .  52            push    edx                                     ; /pThreadId
  00409D98   .  57            push    edi                                     ; |CreationFlags
  00409D99   .  68 346E4100   push    00416E34                                ; |pThreadParm = digi_dum.00416E34
  00409D9E   .  68 10964000   push    00409610                                ; |ThreadFunction = digi_dum.00409610
  00409DA3   .  57            push    edi                                     ; |StackSize
  00409DA4   .  57            push    edi                                     ; |pSecurity
  00409DA5   .  891D E06E4100 mov     [416EE0], ebx                           ; |
  00409DAB   .  FF15 54104100 call    [<&kernel32.CreateThread>]              ; \CreateThread
  
  又建了一个线程,太可疑,线程函数时00409610,跟进去:
  
  00409610   .  53            push    ebx
  00409611   .  56            push    esi
  00409612   .  57            push    edi
  00409613   .  E8 38FDFFFF   call    00409350            ;<-- 有call了,跟进去
  00409618   .  83F8 01       cmp     eax, 1
  0040961B   .  75 17         jnz     short 00409634
  
  跟到00409350:
  
  00409350  /$  6A FF         push    -1
  00409352  |.  68 8B084100   push    0041088B                                ;  SE 处理程序安装
  00409357  |.  64:A1 0000000>mov     eax, fs:[0]
  ...
  00409384  |.  E8 27610000   call    <jmp.&mfc42.#540_CString::CString>
  00409389  |.  56            push    esi                                     ; /ProcessID
  0040938A  |.  6A 02         push    2                                       ; |Flags = TH32CS_SNAPPROCESS
  0040938C  |.  89B424 440100>mov     [esp+144], esi                          ; |
  00409393  |.  E8 7C690000   call    <jmp.&kernel32.CreateToolhelp32Snapshot>; \CreateToolhelp32Snapshot
  00409398  |.  8BF8          mov     edi, eax
  ...
  004093C5  |.  8D4C24 0C     lea     ecx, [esp+C]
  004093C9  |.  E8 DC600000   call    <jmp.&mfc42.#860_CString::operator=>
  004093CE  |.  68 F05D4100   push    00415DF0                                ;  ASCII "SyGate.exe"
  004093D3  |.  8D4C24 0C     lea     ecx, [esp+C]
  004093D7  |.  E8 70640000   call    <jmp.&mfc42.#2764_CString::Find>
  004093DC  |.  3BC6          cmp     eax, esi
  004093DE  |.  0F8F C1010000 jg      004095A5
  004093E4  |>  68 E45D4100   /push    00415DE4                               ;  ASCII "Sygate.exe"
  004093E9  |.  8D4C24 0C     |lea     ecx, [esp+C]
  004093ED  |.  E8 5A640000   |call    <jmp.&mfc42.#2764_CString::Find>
  004093F2  |.  3BC6          |cmp     eax, esi
  ...
  
  这样一看就很清楚了,这里创建了系统进程列表,逐项比对,来确定没有使用代理和BT程序的。
  
  所以没错,之前受怀疑的00403AC0就是检测函数,我们来动个小小手术:
  
  从:
  00403AEB   .  6A 00         push    0
  00403AED   .  6A 00         push    0
  00403AEF   .  6A 00         push    0
  00403AF1   .  6A 00         push    0
  00403AF3   .  51            push    ecx
  00403AF4   .  68 109C4000   push    00409C10
  00403AF9   .  E8 E0BB0000   call    <jmp.&mfc42.#1105_AfxBeginThread>
  
  改为:
  
  00403AEB   .- E9 10932100   jmp     0061CE00
  00403AF0      90            nop
  00403AF1   .  6A 00         push    0
  00403AF3   .  51            push    ecx
  00403AF4   .  68 109C4000   push    00409C10
  00403AF9   .  E8 E0BB0000   call    <jmp.&mfc42.#1105_AfxBeginThread>
  
  然后在 0061CE00处汇编:
  
  0061CE00   /EB 13           jmp     short 0061CE15
  0061CE02   |6A 00           push    0
  0061CE04   |6A 00           push    0
  0061CE06   |6A 00           push    0
  0061CE08   |6A 00           push    0
  0061CE0A   |51              push    ecx
  0061CE0B   |68 109C4000     push    00409C10
  0061CE10   |E8 C928DFFF     call    <jmp.&mfc42.#1105_AfxBeginThread>
  0061CE15  -\E9 E46CDEFF     jmp     00403AFE
  0061CE1A    8B1D 50CC6100   mov     ebx, [61CC50]          ;61CC50就是我们的Getnotest函数
  0061CE20    83FB 00         cmp     ebx, 0                 ;返回为0就执行检测,否则不执行
  0061CE23  ^ 74 DD           je      short 0061CE02
  0061CE25    FFD3            call    ebx
  0061CE27    83F8 00         cmp     eax, 0
  0061CE2A  ^ 74 D6           je      short 0061CE02
  0061CE2C  ^ EB E2           jmp     short 0061CE10
  0061CE2E    90              nop
  
  复制到可执行文件,保存。至此,代理和BT检测也被破除。
  
  八、(R&B)最后的战役
  
  最后,最后我们还要干嘛呢? 嗯,发现没,Digi的体重已经变到了惊人的2.23MB!
  (虽然我一再说Size不重要,可是拥有姚明的脸蛋和李宇春的身材也不是那么的令人茶饭不思吧)
  
  减肥一下,用LordPE打开修改好的Digi,点击"Rebuild PE",对话框选择刚刚修改过的Digi,小灯从红色变为绿色,成功。
  
  瘦身后的Digi回复完美身材207KB。至此,封锁线完全突破成功!!
  ([手捧小金人] 感谢CCTV,MTV,Channel-V,感谢我的家人和长期以来支持我的扇子们,我爱你们!!)
  
--------------------------------------------------------------------------------
【经验总结】
  至此,我们已经彻底的突破了客户端对我们的封锁,天接着很蓝,网继续很宽,资源可以共享,BT随便可以下。。。
  
  代码编写中的关键点有:
   1. 网络发包离不开 wsock32.sendto函数
   2. 窗体消息的突破口在 CCmdTarget::OnCmdMsg函数
   3. 注意消息表的结构,那就是mfc的MESSAGE_MAP宏做的事情
   4. 加入自己的dll用 kernel32.LoadLibraryA函数载入文件和用 kernel32.GetProcAddress函数取得函数地址
   5. 懂一点汇编
   6. 再懂一点C
   7. Size matters, kinda hard to admit though.
  
  突破封锁线:第四章--代码篇 [完]
  
  谢谢您耐心的看到这里,在下一章--外围篇中,将讲述如何不攻入程序内部而改变程序行为,以及dll注入技术。
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2006年05月13日 2:42:37


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 7
支持
分享
最新回复 (34)
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
2006-5-13 21:28
0
雪    币: 47147
活跃值: (20455)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
3
最初由 austiny 发布
下一章--外围篇中,将讲述如何不攻入程序内部而改变程序行为,以及dll注入技术。


期待~
文章写的不错,提高你一些论坛权限  
2006-5-13 21:33
0
雪    币: 109
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
确定一定以及肯定的说:这篇文章写的太好了!
2006-5-13 21:35
0
雪    币: 235
活跃值: (100)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
5
最初由 kanxue 发布
期待~
文章写的不错,提高你一些论坛权限


谢谢老大的鼓励。呵呵
2006-5-13 21:38
0
雪    币: 184
活跃值: (108)
能力值: ( LV9,RANK:410 )
在线值:
发帖
回帖
粉丝
6
不错,在消息表移动的处理上有实用性,今后加自己的东西可以十分方便,比CMP je的方式强,楼主功底扎实,文章潇洒,喜欢.......
2006-5-13 22:37
0
雪    币: 6051
活跃值: (1441)
能力值: ( LV15,RANK:1473 )
在线值:
发帖
回帖
粉丝
7
强就一个字!

期待继续!
2006-5-13 23:45
0
雪    币: 465
活跃值: (667)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
8
厉害,羡慕ing...
谢谢分享,我等菜鸟有救啦
快点出下集啊,上瘾了。。。
2006-5-14 00:06
0
雪    币: 223
活跃值: (70)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
9
将00411818的内容改为 0061C518,这就是新消息表的地址。

应该是00411814吧
2006-5-14 10:25
0
雪    币: 238
活跃值: (326)
能力值: ( LV12,RANK:450 )
在线值:
发帖
回帖
粉丝
10
写的非常不错,希望继续打造好文章。
2006-5-14 10:33
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hxx
11
水平很高
2006-5-14 10:44
0
雪    币: 203
活跃值: (209)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
好文章,期待下一篇。。。。。。。
2006-5-14 14:03
0
雪    币: 236
活跃值: (35)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
13
沙发不是我的!我好喜欢这样的文章 详细!
2006-5-14 16:12
0
雪    币: 253
活跃值: (25)
能力值: ( LV9,RANK:290 )
在线值:
发帖
回帖
粉丝
14
好文,又带点幽默,强力支持!
2006-5-14 16:26
0
雪    币: 136
活跃值: (429)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
15
先顶再说了。。。
2006-5-14 19:08
0
雪    币: 214
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
正需要这方面的文章,强。
2006-5-14 20:37
0
雪    币: 250
活跃值: (103)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
17
好文!
2006-5-14 21:13
0
雪    币: 671
活跃值: (723)
能力值: ( LV9,RANK:1060 )
在线值:
发帖
回帖
粉丝
18
天接着很蓝,网继续很宽,资源可以共享,BT随便可以下。

共产主义万岁!
1. 网络发包离不开 wsock32.sendto函数
2. 窗体消息的突破口在 CCmdTarget::OnCmdMsg函数
3. 注意消息表的结构,那就是mfc的MESSAGE_MAP宏做的事情
4. 加入自己的dll用 kernel32.LoadLibraryA函数载入文件和用 kernel32.GetProcAddress函数取得函数地址
5. 懂一点汇编
6. 再懂一点C
7. Size matters, kinda hard to admit though.

强!精!
2006-5-14 21:59
0
雪    币: 175
活跃值: (2531)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
支持文章写下去。
2006-5-15 11:47
0
雪    币: 159
活跃值: (339)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
20
呵呵...盼了好多天。天天到看雪上来就为这篇文章了....
2006-5-15 14:28
0
雪    币: 333
活跃值: (40)
能力值: ( LV9,RANK:730 )
在线值:
发帖
回帖
粉丝
21
认真学习,期待下一篇
2006-5-15 17:55
0
雪    币: 209
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
从中偶学习了不少。不错的楼主
2006-5-15 19:20
0
雪    币: 95
活跃值: (419)
能力值: ( LV9,RANK:310 )
在线值:
发帖
回帖
粉丝
23
好东西,收藏ing ,,,
有人整理么?
2006-5-15 23:10
0
雪    币: 241
活跃值: (35)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
顶了再说。。。
lz可以写小说了
2006-5-16 00:18
0
雪    币: 465
活跃值: (667)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
25
一路看过来,这边风景独好。谢谢楼主辛勤奉献,真是我等菜鸟的福音。
   一路跟过来,直到此篇,真是不易啊(谁叫我菜呢)。前几篇写的真是不错啊,思路清晰,不乏乐趣,引人入胜。两个字:精彩。(虽然有少许笔误,相信大虾一定是长时间看电脑,眼有点花了,注意身体啊,(民间偏方:多看美女,养眼又舒心,听说还可长寿 ))
    书归正传,到此篇开头:
-----------
“用OllyDbg打开DIGI,停在入口处:
  
  0040FB74 >/$  68 A82A4100   push    00412AA8
  0040FB79  |.  68 D4FC4000   push    <jmp.&msvcrt._except_handler3>   ;  SE 处理程序安装
  0040FB7E  |.  64:A1 0000000>mov     eax, fs:[0]
  
  网络应用程序发送数据包,最后都要用到wsock32.dll中的sendto函数。找到这个函数,就能找到调用它的发包函数。
  
  在CPU窗口中点击Ctrl+N查看当前模块中的名称,果然发现了对sendto函数的引用:
  
  ...
  00411538   .rdata     输入    (    user32.SendMessageA
  00411598   .rdata     输入    (    wsock32.sendto
  00411064   .rdata     输入    (    kernel32.SetEvent
  ...”
---------------
为何我的CTRL-N显示的和你的不一样,地址都是6打头的而不是4开始的,其中并无WSOCK32.SENDTO,我用OD装载得是修改好资源的DIGI.后来我装载原版的DIGI,CTRL-N也没找到楼主所说的00411598   .rdata     输入    (    wsock32.sendto    这句。我查找所有模块调用CALL,便能找到所有楼主说的sendto地址。我想知道CTRL-N为什么不行,为什么和你的不一样???

另:“注意到按钮处理函数的地址已经被写到0061C76C和0061C79C的消息表项中”-------怎么理解?自动生成的?手写的?如何生成的啊

希望楼主有空看看,期待你的下一篇好文。
2006-5-16 02:36
0
游客
登录 | 注册 方可回帖
返回
//