-
-
[旧帖] [原创]某DCS的实时数据的获取分析 0.00雪花
-
发表于: 2009-5-6 09:50 3044
-
【软件名称】: 为维护软件版权,暂称为某 DCS 软件
【加壳方式】: 无壳
【使用工具】: OD,LoadPE
【操作平台】: winxp
【文章简介】: 新手的学习逆向分析笔记,没有技术含量,老手们勿看。目的是获取自己所需要的DCS数据,把它们写到一个INI文件中去。
一、第一阶段笔记:
1、因为该DCS的实时数据的显示是由监控软件xxxx.exe来实现的,所以应该从其入手,分析并掌握它从数据采集到显示的整个过程,然后就可以编制自己的代码,得到自己需要的数据。
2、peid查看,无加密壳,源程序语言为Microsoft Visual C++ 5.0 [调试]
3、OllyICE打开程序,查看调用参考,太多的MFC动态库中未识别的函数。因此添加MFCN42D.LIB和MFC42D.LIB两个文件到OllyICE\LIB目录下。重新查看调用参考,函数已经正常识别出来。可以判断程序大量使用了MFC编程。
4、因为该DCS控制站和上位机之间的通信采用的是TCP/IP协议,而自己对网络有关的软硬件知识又没有,所以只能临时抱佛脚,从网络上下载了许多的关于Microsoft Visual C++ 和MFC的资料。简单了解了以下内容:
Socket通常(但不专用于)与主宰Internet通信的传输控件协议/因特网协议(TCP/IP:Transmission Control Protocol/Internet Protocol)牵连在一起。当Socket与TCP/IP合用时,Socket就是TCP/IP的通讯端点。因此,Socket指定了IP地址和端口号。
TCP/IP的socket提供下列三种类型套接字。
流式套接字(SOCK_STREAM)
提供了一个面向连接、可靠的数据传输服务,数据无差错、无重复地发送,且按发送顺序接收。内设流量控制,避免数据流超限;数据被看作是字节流,无长度限制。文件传送协议(FTP)即使用流式套接字。
数据报式套接字(SOCK_DGRAM)
提供了一个无连接服务。数据包以独立包形式被发送,不提供无错保证,数据可能丢失或重复,并且接收顺序混乱。
原始式套接字(SOCK_RAW)
该接口允许对较低层协议,如IP、ICMP直接访问。常用于检验新的协议实现或访问现有服务中配置的新设备
5、OllyICE打开程序,在所有和socket有关的函数上下断点。因为函数调用太多,要找到所需的断点真是费了很长时间。F9执行程序,中断在:
00409C45 . E8 CA461400 call <jmp.&MFCN42D.#277_AfxSocketInit>
BOOL AfxSocketInit( WSADATA* lpwsaData = NULL );
返回值:如果函数成功执行,则返回非零值,否则为0。
参数: lpwsaData 指向WSADATA结构的指针。如果lpwsaData不等于NULL,那么调用::WSAStartup将填充WSADATA结构。这个 函数同时也保证在应用程序之前调用::WSACleanup。
说明:在你重载的CWinApp::InitInstance函数中调用这个函数以初始化WindowsSockets。
00426444 . E8 317F1200 call <jmp.&MFCN42D.#259_CSocket::CSocket>
此成员函数用来构造一个CSocket对象。在构造之后,你必须调用Create成员函数。
004A400C . E8 8DA30A00 call <jmp.&MFCN42D.#301_CSocket::Create>
BOOL Create( UINT nSocketPort = 0, int nSocketType = SOCK_STREAM, LPCTSTR lpszSocketAddress = NULL );
返回值:如果函数成功则返回非零值;否则返回0,并通过调用GetLastError可以获得特定的错误代码。
参数: nSocketPort 一个要被此插槽使用的特别的端口,如果你希望MFC来选择一个端口,则这个值是0。
nSocketType 是SOCK_STREAM或SOCK_DGRAM。
lpszSocketAddress 一个指向字符串的指针,该字符串包含了被连接插槽的网络地址。一个带点的数字,如“128.56.22.8”。
说明:
在构造一个插槽对象之后,调用Create成员函数来创建Windows 插槽并连接它。然后Create调用Bind来将此插槽与指定的地 址结合。下面就是所支持的插槽类型:
· SOCK_STREAM 提供连续的,可靠的,两种方法(two-way)的,基于连接的字节流。
· SOCK_DGRAM 支持无连接的数据包,它有具有固定(通常较小)最大长度的不可靠的缓冲。
004ACC0F |. E8 66170A00 call <jmp.&MFCN42D.#259_CSocket::CSocket>
004ACB8D . E8 0C180A00 call <jmp.&MFCN42D.#301_CSocket::Create>
默认画面的时候,将不断循环以下的四句代码:
-------------------------------------------------------------------------------------------------------------------
004ACEA5 . E8 DC140A00 call <jmp.&MFCN42D.#347_CAsyncSocket::ReceiveFrom>
本函数用于接收数据报,并把源地址存在SOCKADDR结构或者rSocketAddress指向的地址中。它读取套接字上的数据(可能是 连接上的)并获得发送数据的地址。
实际是接收0x1919端口上的诊断数据。
004ABC27 |. E8 60270A00 call <jmp.&MFCN42D.#337_CAsyncSocket::OnReceive>
本函数由框架调用,通知套接字缓冲中有数据,可以调用Receive成员函数取出
004265AB |. E8 DC7D1200 call <jmp.&MFCN42D.#337_CAsyncSocket::OnReceive>
004265FA |. E8 877D1200 call <jmp.&MFCN42D.#347_CAsyncSocket::ReceiveFrom> ;时钟同步数据
-------------------------------------------------------------------------------------------------------------------
二、第二阶段笔记:
第一阶段未能达到目的后,决定从数据的显示入手,先找到被显示的数据,然后逐步溯源到数据的来龙去脉。
1、经过试验只有下断点USER32.DrawTextA,才能断下。从断点->--杂项--DrawTextA,下断点,F9运行,切换到数据显示画面,中断在下面:
77D3C739 > 8BFF mov edi, edi
ALT + F9,执行到返回程序代码中,来到004B6BC4:
004B6BA0 |. 51 push ecx ; /Flags
004B6BA1 |. 8D55 F0 lea edx, dword ptr [ebp-10] ; |
004B6BA4 |. 52 push edx ; |pRect
004B6BA5 |. 8B45 0C mov eax, dword ptr [ebp+C] ; |
004B6BA8 |. 83C0 10 add eax, 10 ; |
004B6BAB |. 50 push eax ; |/String
004B6BAC |. FF15 18EF6500 call dword ptr [<&KERNEL32.lstrlenA>] ; |\lstrlenA
004B6BB2 |. 50 push eax ; |Count
004B6BB3 |. 8B4D 0C mov ecx, dword ptr [ebp+C] ; |
004B6BB6 |. 83C1 10 add ecx, 10 ; |
004B6BB9 |. 51 push ecx ; |Text
004B6BBA |. 8B55 08 mov edx, dword ptr [ebp+8] ; |
004B6BBD |. 52 push edx ; |hDC
004B6BBE |. FF15 6C066600 call dword ptr [<&USER32.DrawTextA>] ; \DrawTextA
004B6BC4 |. 8B45 E8 mov eax, dword ptr [ebp-18] ;来到这里
在004B6BBE F2下断点,并清除菜单中下的DrawTextA断点。
2、F9多次执行后,发现程序进入正常的数据刷新中,但却不会再次中断在004B6BBE的断点。判断,该处应该是只写一次数据后,就不会再被执行了,所以和实时数据无关。必须重复1的过程,寻找正确的断点。将会找到:
004B7465 . FF15 6C066600 call dword ptr [<&USER32.DrawTextA>] ; \DrawTextA
3、设置新的断点,并重新执行程序:单步执行就会发现被写屏的数据来自于004B715A call dword ptr [<&MSVCRTD.sprintf>]
......
004B7149 . DD1C24 fstp qword ptr [esp]
004B714C . 8B55 0C mov edx,dword ptr [ebp+C] ; 格式符表送edx
004B714F . 83C2 28 add edx,28
004B7152 . 52 push edx ; |format
004B7153 . 8D85 F4FEFFFF lea eax,dword ptr [ebp-10C] ; |
004B7159 . 50 push eax ; |s
004B715A . FF15 AC026600 call dword ptr [<&MSVCRTD.sprintf>] ; \格式化数据
.....
004B7444 . 51 push ecx ; /Flags
004B7445 . 8D95 E4FEFFFF lea edx,dword ptr [ebp-11C] ; |
004B744B . 52 push edx ; |pRect
004B744C . 8D85 F4FEFFFF lea eax,dword ptr [ebp-10C] ; |
004B7452 . 50 push eax ; |/String
004B7453 . FF15 18EF6500 call dword ptr [<&KERNEL32.lstrlenA>] ; |\lstrlenA
004B7459 . 50 push eax ; |Count
004B745A . 8D8D F4FEFFFF lea ecx,dword ptr [ebp-10C] ; |
004B7460 . 51 push ecx ; |Text
004B7461 . 8B55 08 mov edx,dword ptr [ebp+8] ; |
004B7464 . 52 push edx ; |hDC
004B7465 . FF15 6C066600 call dword ptr [<&USER32.DrawTextA>] ; \写屏显的实时数据!!
4、仔细分析004B715A call dword ptr [<&MSVCRTD.sprintf>] 的数据来源,会找到:
004B6F41 . E8 93B3F4FF call 004022D9
这是关键函数,完成了所有的运算任务。被显示的数据,会存放在【eax+4】中
5、跟进 004B6F41 call 004022D9 中去:
(》
......
0043DB6B . E8 FA65FCFF call 0040416A
(
0043CBB0 . E8 7957FCFF call 0040232E ; 根据入口参数取数据地址
0043CBB5 . 8985 2CFFFFFF mov dword ptr [ebp-D4],eax ; 过程返回值送存
0043CBBB . 83BD 2CFFFFFF>cmp dword ptr [ebp-D4],0
0043CBC2 . 74 20 je short 0043CBE4
0043CBC4 . 8B45 0C mov eax,dword ptr [ebp+C]
0043CBC7 . 8B8D 2CFFFFFF mov ecx,dword ptr [ebp-D4] ; ecx=过程返回值
0043CBCD . 66:8B11 mov dx,word ptr [ecx] ; ecx内容送dx。实际为显示值在微机中的表示
0043CBD0 . 66:8950 04 mov word ptr [eax+4],dx ; dx送存
......
)
..............
0043DC1E . E8 B943FCFF call 00401FDC ; 线性变化数据浮点转化
0043DC23 . 83C4 0C add esp,0C
0043DC26 . 8B55 0C mov edx,dword ptr [ebp+C]
0043DC29 . D95A 04 fstp dword ptr [edx+4] ; 被显示的数据存入【edx+4】
......
《)
会发现处理显示值的关键是:0043DB6B . E8 FA65FCFF call 0040416A
***************************************************************
*继续跟进: 0043DB6B . E8 FA65FCFF call 0040416A *
***************************************************************
0043CA90 > \55 push ebp
0043CA91 . 8BEC mov ebp,esp
0043CA93 . 6A FF push -1
......
0043CAC3 . 8D85 34FFFFFF lea eax,dword ptr [ebp-CC]
0043CAC9 . 50 push eax
0043CACA . 8B4D 08 mov ecx,dword ptr [ebp+8] ; AI描述数据地址送ecx
=========================================================================================
001BA2B0 01 0A 35 00 00 00 35 00 25 34 2E 32 66 00 00 00 .5...5.%4.2f...
001BA2C0 00 00 00 00 00 00 00 00 00 00 01 00 ED FF FF FF ...........?
001BA2D0 00 00 00 00 00 00 00 00 00 00 00 00 BC 02 00 00 ............?..
=========================================================================================
0043CACD . 51 push ecx
0043CACE . E8 2C7DFCFF call 004047FF ; 该过程包括很多内容
0043CAD3 . 83C4 08 add esp,8
0043CAD6 . 6A 0C push 0C ; /n = C (12.)
0043CAD8 . 6A 00 push 0 ; |c = 00
0043CADA . 8B55 0C mov edx,dword ptr [ebp+C] ; |
0043CADD . 52 push edx ; |s
0043CADE . E8 190D1100 call <jmp.&MSVCRTD.memset> ; \memset
0043CAE3 . 83C4 0C add esp,0C
0043CAE6 . 8B4D 08 mov ecx,dword ptr [ebp+8] ; AI描述数据地址送ecx
0043CAE9 . E8 9F5DFCFF call 0040288D ; 取参数内容的第1字节送al
0043CAEE . 25 FF000000 and eax,0FF
0043CAF3 . 3D D0000000 cmp eax,0D0 ; 是否等于D0
0043CAF8 . 75 29 jnz short 0043CB23
0043CAFA . 8B0D 6C6A6400 mov ecx,dword ptr [646A6C] ; xxxx.0063C650
0043CB00 . E8 9C80FCFF call 00404BA1
0043CB05 . 8B4D 0C mov ecx,dword ptr [ebp+C]
0043CB08 . 66:8941 04 mov word ptr [ecx+4],ax
0043CB0C . C745 FC FFFFF>mov dword ptr [ebp-4],-1
0043CB13 . 8D8D 34FFFFFF lea ecx,dword ptr [ebp-CC]
0043CB19 . E8 6783FCFF call 00404E85
0043CB1E . E9 74040000 jmp 0043CF97
0043CB23 > 8B4D 08 mov ecx,dword ptr [ebp+8] ; AI描述数据地址送ecx
0043CB26 . E8 EC55FCFF call 00402117 ; 取参数内容的第2字节送al。实际为数据所属CS站号
0043CB2B . 25 FF000000 and eax,0FF ; 高24位置0
0043CB30 . 8B1485 785064>mov edx,dword ptr [eax*4+645078] ;内存表首地址送edx
0043CB37 . 8995 30FFFFFF mov dword ptr [ebp-D0],edx
0043CB3D . 83BD 30FFFFFF>cmp dword ptr [ebp-D0],0
0043CB44 . 75 17 jnz short 0043CB5D
0043CB46 . C745 FC FFFFF>mov dword ptr [ebp-4],-1
0043CB4D . 8D8D 34FFFFFF lea ecx,dword ptr [ebp-CC]
0043CB53 . E8 2D83FCFF call 00404E85
0043CB58 . E9 3A040000 jmp 0043CF97
0043CB5D > 8B4D 08 mov ecx,dword ptr [ebp+8] ; AI描述数据地址送ecx
0043CB60 . E8 285DFCFF call 0040288D ; 取参数内容的第1字节送al
0043CB65 . 25 FF000000 and eax,0FF ; 高24位置0
0043CB6A . 8985 18FFFFFF mov dword ptr [ebp-E8],eax
0043CB70 . 8B85 18FFFFFF mov eax,dword ptr [ebp-E8]
0043CB76 . 83E8 01 sub eax,1 ; eax=参数第1字节值-1
0043CB79 . 8985 18FFFFFF mov dword ptr [ebp-E8],eax
0043CB7F . 83BD 18FFFFFF>cmp dword ptr [ebp-E8],57
0043CB86 . 0F87 F9030000 ja 0043CF85
0043CB8C . 8B95 18FFFFFF mov edx,dword ptr [ebp-E8]
0043CB92 . 33C9 xor ecx,ecx
0043CB94 . 8A8A E8CF4300 mov cl,byte ptr [edx+43CFE8]
0043CB9A . FF248D A8CF43>jmp dword ptr [ecx*4+43CFA8]
0043CBA1 > 8B4D 08 mov ecx,dword ptr [ebp+8] ; AI描述数据地址送ecx
0043CBA4 . E8 F357FCFF call 0040239C ; 取得AI量的序号(偏移2字节的字)送ax
0043CBA9 . 50 push eax
0043CBAA . 8B8D 30FFFFFF mov ecx,dword ptr [ebp-D0] ;内存表首地址
0043CBB0 . E8 7957FCFF call 0040232E ; 根据入口参数取数据地址
==========================================================================================================
a、有两个入口参数:描述数据的第2个字节值(当前ecx=35h)和一个内存记录表的起始地址(当前为01C83A38)
b、(call 0040232E) 的执行内容为:内存记录表偏移2EF2的内容送eax,然后AI量的序号乘上4,二者相加值的地址的内容作为返回值送到eax。
即: lea eax,dword ptr [eax+ecx*4]
c、该实时数据是有哪部分程序段写入的?设内存写入断点时,报“调试的程序无法处理例外”,而终止运行。而且能看到该区域的许多数据在发生变化,应该是所有数据的内存值表。
===========================================================================================================
0043CBB5 . 8985 2CFFFFFF mov dword ptr [ebp-D4],eax
0043CBBB . 83BD 2CFFFFFF>cmp dword ptr [ebp-D4],0
0043CBC2 . 74 20 je short 0043CBE4
0043CBC4 . 8B45 0C mov eax,dword ptr [ebp+C]
0043CBC7 . 8B8D 2CFFFFFF mov ecx,dword ptr [ebp-D4] ; ecx=call 0040232E的返回值
0043CBCD . 66:8B11 mov dx,word ptr [ecx] ; ecx内容送dx。实际为显示值在微机中的表示
0043CBD0 . 66:8950 04 mov word ptr [eax+4],dx ; dx送存
0043CBD4 . 8B45 0C mov eax,dword ptr [ebp+C]
0043CBD7 . 8B8D 2CFFFFFF mov ecx,dword ptr [ebp-D4]
0043CBDD . 66:8B51 02 mov dx,word ptr [ecx+2]
0043CBE1 . 66:8910 mov word ptr [eax],dx
0043CBE4 > E9 9C030000 jmp 0043CF85
0043CBE9 > 8B45 0C mov eax,dword ptr [ebp+C]
0043CBEC . 83C0 04 add eax,4
0043CBEF . 50 push eax
0043CBF0 . 8B4D 08 mov ecx,dword ptr [ebp+8]
.....
0043CF9A . 64:890D 00000>mov dword ptr fs:[0],ecx
0043CFA1 . 5F pop edi
0043CFA2 . 5E pop esi
0043CFA3 . 5B pop ebx
0043CFA4 . 8BE5 mov esp,ebp
0043CFA6 . 5D pop ebp
0043CFA7 . C3 retn
6、继续追溯数据的源头:单步执行找到004B97AA call 00401B04,再单步执行找到:
004D1081 |. E8 BC35F3FF |call 00404642 ; 写屏显数据
***********************************************************************
004D0FE4 |> \C785 F0FEFFFF>mov dword ptr [ebp-110], 0
004D0FEE |. EB 0F jmp short 004D0FFF
004D0FF0 |> 8B85 F0FEFFFF /mov eax, dword ptr [ebp-110]
004D0FF6 |. 83C0 01 |add eax, 1
004D0FF9 |. 8985 F0FEFFFF |mov dword ptr [ebp-110], eax
004D0FFF |> 8B8D 04FFFFFF mov ecx, dword ptr [ebp-FC]
004D1005 |. 33D2 |xor edx, edx
004D1007 |. 66:8B51 08 |mov dx, word ptr [ecx+8]
004D100B |. 3995 F0FEFFFF |cmp dword ptr [ebp-110], edx
004D1011 |. 7D 7B |jge short 004D108E
004D1013 |. 8B85 F0FEFFFF |mov eax, dword ptr [ebp-110]
004D1019 |. 8B8D 04FFFFFF |mov ecx, dword ptr [ebp-FC]
004D101F |. 8B5481 16 |mov edx, dword ptr [ecx+eax*4+16]
004D1023 |. 8995 E4FEFFFF |mov dword ptr [ebp-11C], edx
004D1029 |. 8B85 E4FEFFFF |mov eax, dword ptr [ebp-11C]
004D102F |. 8B8D 04FFFFFF |mov ecx, dword ptr [ebp-FC]
004D1035 |. 8D9401 162000>|lea edx, dword ptr [ecx+eax+2016]
004D103C |. 8995 E0FEFFFF |mov dword ptr [ebp-120], edx
004D1042 |. 8B85 E0FEFFFF |mov eax, dword ptr [ebp-120]
004D1048 |. 33C9 |xor ecx, ecx
004D104A |. 66:8B48 0E |mov cx, word ptr [eax+E]
004D104E |. 85C9 |test ecx, ecx
004D1050 |. 74 37 |je short 004D1089
004D1052 |. 8B95 E0FEFFFF |mov edx, dword ptr [ebp-120]
004D1058 |. 33C0 |xor eax, eax
004D105A |. 66:8B42 0C |mov ax, word ptr [edx+C]
004D105E |. 85C0 |test eax, eax
004D1060 |. 74 27 |je short 004D1089
004D1062 |. 8B8D E0FEFFFF |mov ecx, dword ptr [ebp-120]
004D1068 |. 33D2 |xor edx, edx
004D106A |. 66:8B51 08 |mov dx, word ptr [ecx+8]
004D106E |. 83FA 70 |cmp edx, 70
004D1071 |. 74 16 |je short 004D1089
004D1073 |. 8B85 E0FEFFFF |mov eax, dword ptr [ebp-120]
004D1079 |. 50 |push eax
004D107A |. 8B0D 24C06500 |mov ecx, dword ptr [65C024]
004D1080 |. 51 |push ecx
004D1081 |. E8 BC35F3FF |call 00404642
004D1086 |. 83C4 08 |add esp, 8
004D1089 |>^ E9 62FFFFFF \jmp 004D0FF0
***********************************************************************
分析可知上面的循环,每当条件满足,就执行一次call 00404642,完成向屏幕写数据的任务。
004D1019 |. 8B8D 04FFFFFF |mov ecx, dword ptr [ebp-FC] 这里ecx会被用来查表,然后处理查到的数据
004D1035 |. 8D9401 162000>|lea edx, dword ptr [ecx+eax+2016] 查询的数据地址存于edx中
查看内存数据格式,得到:
001C97AE A4 00 00 00 00 00 00 00 10 00 00 00 20 00 01 00
001C97BE 3D 01 00 00 21 00 00 00 86 01 00 00 3A 00 00 00
001C97CE 54 52 43 41 31 30 31 2D 31 00 00 00 00 00 00 00
001C97DE 01 02 00 00 00 00 00 00 25 36 2E 32 66 00 00 00
001C97EE 00 00 00 00 00 00 00 00 00 00 01 00 ED FF FF FF
001C97FE 00 00 00 00 00 00 00 00 00 00 00 00 BC 02 00 00
001C980E 00 00 00 86 03 02 01 31 D0 C2 CB CE CC E5 00 32
001C981E 33 31 32 00 00 00 00 00 00 00 00 00 FF FF 00 00
001C982E 2F 2D FF FF 18 04 28 08 00 80 00 00 C0 C0 C0 00
001C983E FF FF 00 00 FF 00 00 00 00 00 00 00 01 00 00 00
001C984E 00 00 00 00 ....
结合DCS数据特点,可分析出:偏移30h起的8个字节就是相应的显示数据在微机中的表示。
因此,可以构造自己所需要的数据的字节串,把它保存在源程序的代码中,然后让程序跳到自己的代码处执行。
三、第三阶段笔记
1、增加数据常量:在OllyICE中搜索字符串参考,双击任何一个进入反汇编窗口,然后右键菜单中选择“数据窗口中跟随--立即数”,然后在数据窗口右键菜单中选择“查看可执行文件”,弹出文件编辑窗口。寻找一空的数据区域,修改为准备增加的数据,然后保存。
2、增加自己的代码:
因为源程序中没有使用WritePrivateProfileString函数,所以利用LoadPE增加该导入函数。
经过多次失败,最后采取的代码如下:
***********************************************************************
修改后:
004D108E |> >jmp 004D36C7
004D1093 | >nop
004D1094 |> >push edx ; /pPaintstruct
004D1095 |. >mov eax,dword ptr [ebp+8] ; |
004D1098 |. >push eax ; |hWnd
004D1099 |. >call dword ptr [<&USER32.BeginPaint>] ; \BeginPaint
修改前:
004D108E |> >lea edx,dword ptr [ebp-F8]
004D1094 |. >push edx ; /pPaintstruct
004D1095 |. >mov eax,dword ptr [ebp+8] ; |
004D1098 |. >push eax ; |hWnd
004D1099 |. >call dword ptr [<&USER32.BeginPaint>] ; \BeginPaint
***********************************************************************
***********************************************************************
004D36C7 |> >push 10 ; /MemSize = 10 (16.)
004D36C9 |. >push 42 ; |Flags = GHND
004D36CB |. >call dword ptr [<&KERNEL32.GlobalAlloc>] ; \GlobalAlloc
004D36D1 |. >mov dword ptr [ebp-3C],eax
004D36D4 |. >mov edx,dword ptr [ebp-3C]
004D36D7 |. >mov ecx,dword ptr [edx]
004D36D9 |. >xor eax,eax
004D36DB |. >mov dword ptr [ebp-110],0
004D36E5 |. >jmp short 004D36F6
004D36E7 |> >/mov eax,dword ptr [ebp-110]
004D36ED |. >|add eax,1
004D36F0 |. >|mov dword ptr [ebp-110],eax
004D36F6 |> > cmp dword ptr [ebp-110],3
004D36FD |. >|jge short 004D371E
004D36FF |. >|mov edx,dword ptr [eax*8+637A40]
004D3706 |. >|mov dword ptr [ecx],edx
004D3708 |. >|mov edx,dword ptr [eax*8+637A44]
004D370F |. >|mov dword ptr [ecx+4],edx
004D3712 |. >|call 004D37D4
004D3717 |. >|mov ecx,dword ptr [ebp-3C]
004D371A |. >|mov ecx,dword ptr [ecx]
004D371C |.^>\jmp short 004D36E7
004D371E |> >lea edx,dword ptr [ebp-F8]
004D3724 \.^>jmp 004D1094
......
004D37D4 /$ >push 10 ; /MemSize = 10 (16.)
004D37D6 |. >push 42 ; |Flags = GHND
004D37D8 |. >call dword ptr [<&KERNEL32.GlobalAlloc>] ; \GlobalAlloc
004D37DE |. >mov dword ptr [ebp-2C],eax
004D37E1 |. >mov ecx,dword ptr [ebp-3C]
004D37E4 |. >mov ecx,dword ptr [ecx]
004D37E6 |. >nop
004D37E7 |. >nop
004D37E8 |. >nop
004D37E9 |. >nop
004D37EA |. >mov al,byte ptr [ecx+1]
004D37ED |. >and eax,0FF
004D37F2 |. >mov edx,dword ptr [eax*4+645078]
004D37F9 |. >test edx,edx
004D37FB |. >je short 004D3871
004D37FD |. >mov ax,word ptr [ecx+2]
004D3801 |. >and ecx,0FFFF
004D3807 |. >mov ecx,eax
004D3809 |. >mov eax,dword ptr [edx+2EF2]
004D380F |. >test eax,eax
004D3811 |. >je short 004D3871
004D3813 |. >lea eax,dword ptr [eax+ecx*4]
004D3816 |. >fild word ptr [eax]
004D3818 |. >fdiv dword ptr [61D214]
004D381E |. >mov eax,dword ptr [ebp-110]
004D3824 |. >shl eax,4
004D3827 |. >add eax,00637900 ; ASCII "XXXXX-1"
004D382C |. >add eax,0C
004D382F |. >fld dword ptr [eax]
004D3831 |. >fmulp st(1),st
004D3833 |. >sub esp,8 ; /<%6.2f>
004D3836 |. >fstp qword ptr [esp] ; |
004D3839 |. >push 00637810 ; |format = "%6.2f"
004D383E |. >mov eax,dword ptr [ebp-2C] ; |
004D3841 |. >push dword ptr [eax] ; |s
004D3843 |. >call dword ptr [<&MSVCRTD.sprintf>] ; \sprintf
004D3849 |. >nop
004D384A |. >push 00637870 ; /FileName = "XXXXX.ini"
004D384F |. >mov eax,dword ptr [ebp-2C] ; |
004D3852 |. >push dword ptr [eax] ; |String
004D3854 |. >mov eax,dword ptr [ebp-110] ; |
004D385A |. >shl eax,4 ; |
004D385D |. >add eax,00637900 ; |ASCII "XXXXX-1"
004D3862 |. >push eax ; |Key
004D3863 |. >push 006378A0 ; |Section = "1#XXXXX"
004D3868 |. >call dword ptr [<&kernel32.WritePrivateProf>; \WritePrivateProfileStringA
004D386E |. >mov eax,dword ptr [ebp-2C]
004D3871 |> >push eax ; /hMem
004D3872 |. >call dword ptr [<&KERNEL32.GlobalFree>] ; \GlobalFree
004D3878 |. >add esp,10
004D387B \. >retn
***********************************************************************
【加壳方式】: 无壳
【使用工具】: OD,LoadPE
【操作平台】: winxp
【文章简介】: 新手的学习逆向分析笔记,没有技术含量,老手们勿看。目的是获取自己所需要的DCS数据,把它们写到一个INI文件中去。
一、第一阶段笔记:
1、因为该DCS的实时数据的显示是由监控软件xxxx.exe来实现的,所以应该从其入手,分析并掌握它从数据采集到显示的整个过程,然后就可以编制自己的代码,得到自己需要的数据。
2、peid查看,无加密壳,源程序语言为Microsoft Visual C++ 5.0 [调试]
3、OllyICE打开程序,查看调用参考,太多的MFC动态库中未识别的函数。因此添加MFCN42D.LIB和MFC42D.LIB两个文件到OllyICE\LIB目录下。重新查看调用参考,函数已经正常识别出来。可以判断程序大量使用了MFC编程。
4、因为该DCS控制站和上位机之间的通信采用的是TCP/IP协议,而自己对网络有关的软硬件知识又没有,所以只能临时抱佛脚,从网络上下载了许多的关于Microsoft Visual C++ 和MFC的资料。简单了解了以下内容:
Socket通常(但不专用于)与主宰Internet通信的传输控件协议/因特网协议(TCP/IP:Transmission Control Protocol/Internet Protocol)牵连在一起。当Socket与TCP/IP合用时,Socket就是TCP/IP的通讯端点。因此,Socket指定了IP地址和端口号。
TCP/IP的socket提供下列三种类型套接字。
流式套接字(SOCK_STREAM)
提供了一个面向连接、可靠的数据传输服务,数据无差错、无重复地发送,且按发送顺序接收。内设流量控制,避免数据流超限;数据被看作是字节流,无长度限制。文件传送协议(FTP)即使用流式套接字。
数据报式套接字(SOCK_DGRAM)
提供了一个无连接服务。数据包以独立包形式被发送,不提供无错保证,数据可能丢失或重复,并且接收顺序混乱。
原始式套接字(SOCK_RAW)
该接口允许对较低层协议,如IP、ICMP直接访问。常用于检验新的协议实现或访问现有服务中配置的新设备
5、OllyICE打开程序,在所有和socket有关的函数上下断点。因为函数调用太多,要找到所需的断点真是费了很长时间。F9执行程序,中断在:
00409C45 . E8 CA461400 call <jmp.&MFCN42D.#277_AfxSocketInit>
BOOL AfxSocketInit( WSADATA* lpwsaData = NULL );
返回值:如果函数成功执行,则返回非零值,否则为0。
参数: lpwsaData 指向WSADATA结构的指针。如果lpwsaData不等于NULL,那么调用::WSAStartup将填充WSADATA结构。这个 函数同时也保证在应用程序之前调用::WSACleanup。
说明:在你重载的CWinApp::InitInstance函数中调用这个函数以初始化WindowsSockets。
00426444 . E8 317F1200 call <jmp.&MFCN42D.#259_CSocket::CSocket>
此成员函数用来构造一个CSocket对象。在构造之后,你必须调用Create成员函数。
004A400C . E8 8DA30A00 call <jmp.&MFCN42D.#301_CSocket::Create>
BOOL Create( UINT nSocketPort = 0, int nSocketType = SOCK_STREAM, LPCTSTR lpszSocketAddress = NULL );
返回值:如果函数成功则返回非零值;否则返回0,并通过调用GetLastError可以获得特定的错误代码。
参数: nSocketPort 一个要被此插槽使用的特别的端口,如果你希望MFC来选择一个端口,则这个值是0。
nSocketType 是SOCK_STREAM或SOCK_DGRAM。
lpszSocketAddress 一个指向字符串的指针,该字符串包含了被连接插槽的网络地址。一个带点的数字,如“128.56.22.8”。
说明:
在构造一个插槽对象之后,调用Create成员函数来创建Windows 插槽并连接它。然后Create调用Bind来将此插槽与指定的地 址结合。下面就是所支持的插槽类型:
· SOCK_STREAM 提供连续的,可靠的,两种方法(two-way)的,基于连接的字节流。
· SOCK_DGRAM 支持无连接的数据包,它有具有固定(通常较小)最大长度的不可靠的缓冲。
004ACC0F |. E8 66170A00 call <jmp.&MFCN42D.#259_CSocket::CSocket>
004ACB8D . E8 0C180A00 call <jmp.&MFCN42D.#301_CSocket::Create>
默认画面的时候,将不断循环以下的四句代码:
-------------------------------------------------------------------------------------------------------------------
004ACEA5 . E8 DC140A00 call <jmp.&MFCN42D.#347_CAsyncSocket::ReceiveFrom>
本函数用于接收数据报,并把源地址存在SOCKADDR结构或者rSocketAddress指向的地址中。它读取套接字上的数据(可能是 连接上的)并获得发送数据的地址。
实际是接收0x1919端口上的诊断数据。
004ABC27 |. E8 60270A00 call <jmp.&MFCN42D.#337_CAsyncSocket::OnReceive>
本函数由框架调用,通知套接字缓冲中有数据,可以调用Receive成员函数取出
004265AB |. E8 DC7D1200 call <jmp.&MFCN42D.#337_CAsyncSocket::OnReceive>
004265FA |. E8 877D1200 call <jmp.&MFCN42D.#347_CAsyncSocket::ReceiveFrom> ;时钟同步数据
-------------------------------------------------------------------------------------------------------------------
二、第二阶段笔记:
第一阶段未能达到目的后,决定从数据的显示入手,先找到被显示的数据,然后逐步溯源到数据的来龙去脉。
1、经过试验只有下断点USER32.DrawTextA,才能断下。从断点->--杂项--DrawTextA,下断点,F9运行,切换到数据显示画面,中断在下面:
77D3C739 > 8BFF mov edi, edi
ALT + F9,执行到返回程序代码中,来到004B6BC4:
004B6BA0 |. 51 push ecx ; /Flags
004B6BA1 |. 8D55 F0 lea edx, dword ptr [ebp-10] ; |
004B6BA4 |. 52 push edx ; |pRect
004B6BA5 |. 8B45 0C mov eax, dword ptr [ebp+C] ; |
004B6BA8 |. 83C0 10 add eax, 10 ; |
004B6BAB |. 50 push eax ; |/String
004B6BAC |. FF15 18EF6500 call dword ptr [<&KERNEL32.lstrlenA>] ; |\lstrlenA
004B6BB2 |. 50 push eax ; |Count
004B6BB3 |. 8B4D 0C mov ecx, dword ptr [ebp+C] ; |
004B6BB6 |. 83C1 10 add ecx, 10 ; |
004B6BB9 |. 51 push ecx ; |Text
004B6BBA |. 8B55 08 mov edx, dword ptr [ebp+8] ; |
004B6BBD |. 52 push edx ; |hDC
004B6BBE |. FF15 6C066600 call dword ptr [<&USER32.DrawTextA>] ; \DrawTextA
004B6BC4 |. 8B45 E8 mov eax, dword ptr [ebp-18] ;来到这里
在004B6BBE F2下断点,并清除菜单中下的DrawTextA断点。
2、F9多次执行后,发现程序进入正常的数据刷新中,但却不会再次中断在004B6BBE的断点。判断,该处应该是只写一次数据后,就不会再被执行了,所以和实时数据无关。必须重复1的过程,寻找正确的断点。将会找到:
004B7465 . FF15 6C066600 call dword ptr [<&USER32.DrawTextA>] ; \DrawTextA
3、设置新的断点,并重新执行程序:单步执行就会发现被写屏的数据来自于004B715A call dword ptr [<&MSVCRTD.sprintf>]
......
004B7149 . DD1C24 fstp qword ptr [esp]
004B714C . 8B55 0C mov edx,dword ptr [ebp+C] ; 格式符表送edx
004B714F . 83C2 28 add edx,28
004B7152 . 52 push edx ; |format
004B7153 . 8D85 F4FEFFFF lea eax,dword ptr [ebp-10C] ; |
004B7159 . 50 push eax ; |s
004B715A . FF15 AC026600 call dword ptr [<&MSVCRTD.sprintf>] ; \格式化数据
.....
004B7444 . 51 push ecx ; /Flags
004B7445 . 8D95 E4FEFFFF lea edx,dword ptr [ebp-11C] ; |
004B744B . 52 push edx ; |pRect
004B744C . 8D85 F4FEFFFF lea eax,dword ptr [ebp-10C] ; |
004B7452 . 50 push eax ; |/String
004B7453 . FF15 18EF6500 call dword ptr [<&KERNEL32.lstrlenA>] ; |\lstrlenA
004B7459 . 50 push eax ; |Count
004B745A . 8D8D F4FEFFFF lea ecx,dword ptr [ebp-10C] ; |
004B7460 . 51 push ecx ; |Text
004B7461 . 8B55 08 mov edx,dword ptr [ebp+8] ; |
004B7464 . 52 push edx ; |hDC
004B7465 . FF15 6C066600 call dword ptr [<&USER32.DrawTextA>] ; \写屏显的实时数据!!
4、仔细分析004B715A call dword ptr [<&MSVCRTD.sprintf>] 的数据来源,会找到:
004B6F41 . E8 93B3F4FF call 004022D9
这是关键函数,完成了所有的运算任务。被显示的数据,会存放在【eax+4】中
5、跟进 004B6F41 call 004022D9 中去:
(》
......
0043DB6B . E8 FA65FCFF call 0040416A
(
0043CBB0 . E8 7957FCFF call 0040232E ; 根据入口参数取数据地址
0043CBB5 . 8985 2CFFFFFF mov dword ptr [ebp-D4],eax ; 过程返回值送存
0043CBBB . 83BD 2CFFFFFF>cmp dword ptr [ebp-D4],0
0043CBC2 . 74 20 je short 0043CBE4
0043CBC4 . 8B45 0C mov eax,dword ptr [ebp+C]
0043CBC7 . 8B8D 2CFFFFFF mov ecx,dword ptr [ebp-D4] ; ecx=过程返回值
0043CBCD . 66:8B11 mov dx,word ptr [ecx] ; ecx内容送dx。实际为显示值在微机中的表示
0043CBD0 . 66:8950 04 mov word ptr [eax+4],dx ; dx送存
......
)
..............
0043DC1E . E8 B943FCFF call 00401FDC ; 线性变化数据浮点转化
0043DC23 . 83C4 0C add esp,0C
0043DC26 . 8B55 0C mov edx,dword ptr [ebp+C]
0043DC29 . D95A 04 fstp dword ptr [edx+4] ; 被显示的数据存入【edx+4】
......
《)
会发现处理显示值的关键是:0043DB6B . E8 FA65FCFF call 0040416A
***************************************************************
*继续跟进: 0043DB6B . E8 FA65FCFF call 0040416A *
***************************************************************
0043CA90 > \55 push ebp
0043CA91 . 8BEC mov ebp,esp
0043CA93 . 6A FF push -1
......
0043CAC3 . 8D85 34FFFFFF lea eax,dword ptr [ebp-CC]
0043CAC9 . 50 push eax
0043CACA . 8B4D 08 mov ecx,dword ptr [ebp+8] ; AI描述数据地址送ecx
=========================================================================================
001BA2B0 01 0A 35 00 00 00 35 00 25 34 2E 32 66 00 00 00 .5...5.%4.2f...
001BA2C0 00 00 00 00 00 00 00 00 00 00 01 00 ED FF FF FF ...........?
001BA2D0 00 00 00 00 00 00 00 00 00 00 00 00 BC 02 00 00 ............?..
=========================================================================================
0043CACD . 51 push ecx
0043CACE . E8 2C7DFCFF call 004047FF ; 该过程包括很多内容
0043CAD3 . 83C4 08 add esp,8
0043CAD6 . 6A 0C push 0C ; /n = C (12.)
0043CAD8 . 6A 00 push 0 ; |c = 00
0043CADA . 8B55 0C mov edx,dword ptr [ebp+C] ; |
0043CADD . 52 push edx ; |s
0043CADE . E8 190D1100 call <jmp.&MSVCRTD.memset> ; \memset
0043CAE3 . 83C4 0C add esp,0C
0043CAE6 . 8B4D 08 mov ecx,dword ptr [ebp+8] ; AI描述数据地址送ecx
0043CAE9 . E8 9F5DFCFF call 0040288D ; 取参数内容的第1字节送al
0043CAEE . 25 FF000000 and eax,0FF
0043CAF3 . 3D D0000000 cmp eax,0D0 ; 是否等于D0
0043CAF8 . 75 29 jnz short 0043CB23
0043CAFA . 8B0D 6C6A6400 mov ecx,dword ptr [646A6C] ; xxxx.0063C650
0043CB00 . E8 9C80FCFF call 00404BA1
0043CB05 . 8B4D 0C mov ecx,dword ptr [ebp+C]
0043CB08 . 66:8941 04 mov word ptr [ecx+4],ax
0043CB0C . C745 FC FFFFF>mov dword ptr [ebp-4],-1
0043CB13 . 8D8D 34FFFFFF lea ecx,dword ptr [ebp-CC]
0043CB19 . E8 6783FCFF call 00404E85
0043CB1E . E9 74040000 jmp 0043CF97
0043CB23 > 8B4D 08 mov ecx,dword ptr [ebp+8] ; AI描述数据地址送ecx
0043CB26 . E8 EC55FCFF call 00402117 ; 取参数内容的第2字节送al。实际为数据所属CS站号
0043CB2B . 25 FF000000 and eax,0FF ; 高24位置0
0043CB30 . 8B1485 785064>mov edx,dword ptr [eax*4+645078] ;内存表首地址送edx
0043CB37 . 8995 30FFFFFF mov dword ptr [ebp-D0],edx
0043CB3D . 83BD 30FFFFFF>cmp dword ptr [ebp-D0],0
0043CB44 . 75 17 jnz short 0043CB5D
0043CB46 . C745 FC FFFFF>mov dword ptr [ebp-4],-1
0043CB4D . 8D8D 34FFFFFF lea ecx,dword ptr [ebp-CC]
0043CB53 . E8 2D83FCFF call 00404E85
0043CB58 . E9 3A040000 jmp 0043CF97
0043CB5D > 8B4D 08 mov ecx,dword ptr [ebp+8] ; AI描述数据地址送ecx
0043CB60 . E8 285DFCFF call 0040288D ; 取参数内容的第1字节送al
0043CB65 . 25 FF000000 and eax,0FF ; 高24位置0
0043CB6A . 8985 18FFFFFF mov dword ptr [ebp-E8],eax
0043CB70 . 8B85 18FFFFFF mov eax,dword ptr [ebp-E8]
0043CB76 . 83E8 01 sub eax,1 ; eax=参数第1字节值-1
0043CB79 . 8985 18FFFFFF mov dword ptr [ebp-E8],eax
0043CB7F . 83BD 18FFFFFF>cmp dword ptr [ebp-E8],57
0043CB86 . 0F87 F9030000 ja 0043CF85
0043CB8C . 8B95 18FFFFFF mov edx,dword ptr [ebp-E8]
0043CB92 . 33C9 xor ecx,ecx
0043CB94 . 8A8A E8CF4300 mov cl,byte ptr [edx+43CFE8]
0043CB9A . FF248D A8CF43>jmp dword ptr [ecx*4+43CFA8]
0043CBA1 > 8B4D 08 mov ecx,dword ptr [ebp+8] ; AI描述数据地址送ecx
0043CBA4 . E8 F357FCFF call 0040239C ; 取得AI量的序号(偏移2字节的字)送ax
0043CBA9 . 50 push eax
0043CBAA . 8B8D 30FFFFFF mov ecx,dword ptr [ebp-D0] ;内存表首地址
0043CBB0 . E8 7957FCFF call 0040232E ; 根据入口参数取数据地址
==========================================================================================================
a、有两个入口参数:描述数据的第2个字节值(当前ecx=35h)和一个内存记录表的起始地址(当前为01C83A38)
b、(call 0040232E) 的执行内容为:内存记录表偏移2EF2的内容送eax,然后AI量的序号乘上4,二者相加值的地址的内容作为返回值送到eax。
即: lea eax,dword ptr [eax+ecx*4]
c、该实时数据是有哪部分程序段写入的?设内存写入断点时,报“调试的程序无法处理例外”,而终止运行。而且能看到该区域的许多数据在发生变化,应该是所有数据的内存值表。
===========================================================================================================
0043CBB5 . 8985 2CFFFFFF mov dword ptr [ebp-D4],eax
0043CBBB . 83BD 2CFFFFFF>cmp dword ptr [ebp-D4],0
0043CBC2 . 74 20 je short 0043CBE4
0043CBC4 . 8B45 0C mov eax,dword ptr [ebp+C]
0043CBC7 . 8B8D 2CFFFFFF mov ecx,dword ptr [ebp-D4] ; ecx=call 0040232E的返回值
0043CBCD . 66:8B11 mov dx,word ptr [ecx] ; ecx内容送dx。实际为显示值在微机中的表示
0043CBD0 . 66:8950 04 mov word ptr [eax+4],dx ; dx送存
0043CBD4 . 8B45 0C mov eax,dword ptr [ebp+C]
0043CBD7 . 8B8D 2CFFFFFF mov ecx,dword ptr [ebp-D4]
0043CBDD . 66:8B51 02 mov dx,word ptr [ecx+2]
0043CBE1 . 66:8910 mov word ptr [eax],dx
0043CBE4 > E9 9C030000 jmp 0043CF85
0043CBE9 > 8B45 0C mov eax,dword ptr [ebp+C]
0043CBEC . 83C0 04 add eax,4
0043CBEF . 50 push eax
0043CBF0 . 8B4D 08 mov ecx,dword ptr [ebp+8]
.....
0043CF9A . 64:890D 00000>mov dword ptr fs:[0],ecx
0043CFA1 . 5F pop edi
0043CFA2 . 5E pop esi
0043CFA3 . 5B pop ebx
0043CFA4 . 8BE5 mov esp,ebp
0043CFA6 . 5D pop ebp
0043CFA7 . C3 retn
6、继续追溯数据的源头:单步执行找到004B97AA call 00401B04,再单步执行找到:
004D1081 |. E8 BC35F3FF |call 00404642 ; 写屏显数据
***********************************************************************
004D0FE4 |> \C785 F0FEFFFF>mov dword ptr [ebp-110], 0
004D0FEE |. EB 0F jmp short 004D0FFF
004D0FF0 |> 8B85 F0FEFFFF /mov eax, dword ptr [ebp-110]
004D0FF6 |. 83C0 01 |add eax, 1
004D0FF9 |. 8985 F0FEFFFF |mov dword ptr [ebp-110], eax
004D0FFF |> 8B8D 04FFFFFF mov ecx, dword ptr [ebp-FC]
004D1005 |. 33D2 |xor edx, edx
004D1007 |. 66:8B51 08 |mov dx, word ptr [ecx+8]
004D100B |. 3995 F0FEFFFF |cmp dword ptr [ebp-110], edx
004D1011 |. 7D 7B |jge short 004D108E
004D1013 |. 8B85 F0FEFFFF |mov eax, dword ptr [ebp-110]
004D1019 |. 8B8D 04FFFFFF |mov ecx, dword ptr [ebp-FC]
004D101F |. 8B5481 16 |mov edx, dword ptr [ecx+eax*4+16]
004D1023 |. 8995 E4FEFFFF |mov dword ptr [ebp-11C], edx
004D1029 |. 8B85 E4FEFFFF |mov eax, dword ptr [ebp-11C]
004D102F |. 8B8D 04FFFFFF |mov ecx, dword ptr [ebp-FC]
004D1035 |. 8D9401 162000>|lea edx, dword ptr [ecx+eax+2016]
004D103C |. 8995 E0FEFFFF |mov dword ptr [ebp-120], edx
004D1042 |. 8B85 E0FEFFFF |mov eax, dword ptr [ebp-120]
004D1048 |. 33C9 |xor ecx, ecx
004D104A |. 66:8B48 0E |mov cx, word ptr [eax+E]
004D104E |. 85C9 |test ecx, ecx
004D1050 |. 74 37 |je short 004D1089
004D1052 |. 8B95 E0FEFFFF |mov edx, dword ptr [ebp-120]
004D1058 |. 33C0 |xor eax, eax
004D105A |. 66:8B42 0C |mov ax, word ptr [edx+C]
004D105E |. 85C0 |test eax, eax
004D1060 |. 74 27 |je short 004D1089
004D1062 |. 8B8D E0FEFFFF |mov ecx, dword ptr [ebp-120]
004D1068 |. 33D2 |xor edx, edx
004D106A |. 66:8B51 08 |mov dx, word ptr [ecx+8]
004D106E |. 83FA 70 |cmp edx, 70
004D1071 |. 74 16 |je short 004D1089
004D1073 |. 8B85 E0FEFFFF |mov eax, dword ptr [ebp-120]
004D1079 |. 50 |push eax
004D107A |. 8B0D 24C06500 |mov ecx, dword ptr [65C024]
004D1080 |. 51 |push ecx
004D1081 |. E8 BC35F3FF |call 00404642
004D1086 |. 83C4 08 |add esp, 8
004D1089 |>^ E9 62FFFFFF \jmp 004D0FF0
***********************************************************************
分析可知上面的循环,每当条件满足,就执行一次call 00404642,完成向屏幕写数据的任务。
004D1019 |. 8B8D 04FFFFFF |mov ecx, dword ptr [ebp-FC] 这里ecx会被用来查表,然后处理查到的数据
004D1035 |. 8D9401 162000>|lea edx, dword ptr [ecx+eax+2016] 查询的数据地址存于edx中
查看内存数据格式,得到:
001C97AE A4 00 00 00 00 00 00 00 10 00 00 00 20 00 01 00
001C97BE 3D 01 00 00 21 00 00 00 86 01 00 00 3A 00 00 00
001C97CE 54 52 43 41 31 30 31 2D 31 00 00 00 00 00 00 00
001C97DE 01 02 00 00 00 00 00 00 25 36 2E 32 66 00 00 00
001C97EE 00 00 00 00 00 00 00 00 00 00 01 00 ED FF FF FF
001C97FE 00 00 00 00 00 00 00 00 00 00 00 00 BC 02 00 00
001C980E 00 00 00 86 03 02 01 31 D0 C2 CB CE CC E5 00 32
001C981E 33 31 32 00 00 00 00 00 00 00 00 00 FF FF 00 00
001C982E 2F 2D FF FF 18 04 28 08 00 80 00 00 C0 C0 C0 00
001C983E FF FF 00 00 FF 00 00 00 00 00 00 00 01 00 00 00
001C984E 00 00 00 00 ....
结合DCS数据特点,可分析出:偏移30h起的8个字节就是相应的显示数据在微机中的表示。
因此,可以构造自己所需要的数据的字节串,把它保存在源程序的代码中,然后让程序跳到自己的代码处执行。
三、第三阶段笔记
1、增加数据常量:在OllyICE中搜索字符串参考,双击任何一个进入反汇编窗口,然后右键菜单中选择“数据窗口中跟随--立即数”,然后在数据窗口右键菜单中选择“查看可执行文件”,弹出文件编辑窗口。寻找一空的数据区域,修改为准备增加的数据,然后保存。
2、增加自己的代码:
因为源程序中没有使用WritePrivateProfileString函数,所以利用LoadPE增加该导入函数。
经过多次失败,最后采取的代码如下:
***********************************************************************
修改后:
004D108E |> >jmp 004D36C7
004D1093 | >nop
004D1094 |> >push edx ; /pPaintstruct
004D1095 |. >mov eax,dword ptr [ebp+8] ; |
004D1098 |. >push eax ; |hWnd
004D1099 |. >call dword ptr [<&USER32.BeginPaint>] ; \BeginPaint
修改前:
004D108E |> >lea edx,dword ptr [ebp-F8]
004D1094 |. >push edx ; /pPaintstruct
004D1095 |. >mov eax,dword ptr [ebp+8] ; |
004D1098 |. >push eax ; |hWnd
004D1099 |. >call dword ptr [<&USER32.BeginPaint>] ; \BeginPaint
***********************************************************************
***********************************************************************
004D36C7 |> >push 10 ; /MemSize = 10 (16.)
004D36C9 |. >push 42 ; |Flags = GHND
004D36CB |. >call dword ptr [<&KERNEL32.GlobalAlloc>] ; \GlobalAlloc
004D36D1 |. >mov dword ptr [ebp-3C],eax
004D36D4 |. >mov edx,dword ptr [ebp-3C]
004D36D7 |. >mov ecx,dword ptr [edx]
004D36D9 |. >xor eax,eax
004D36DB |. >mov dword ptr [ebp-110],0
004D36E5 |. >jmp short 004D36F6
004D36E7 |> >/mov eax,dword ptr [ebp-110]
004D36ED |. >|add eax,1
004D36F0 |. >|mov dword ptr [ebp-110],eax
004D36F6 |> > cmp dword ptr [ebp-110],3
004D36FD |. >|jge short 004D371E
004D36FF |. >|mov edx,dword ptr [eax*8+637A40]
004D3706 |. >|mov dword ptr [ecx],edx
004D3708 |. >|mov edx,dword ptr [eax*8+637A44]
004D370F |. >|mov dword ptr [ecx+4],edx
004D3712 |. >|call 004D37D4
004D3717 |. >|mov ecx,dword ptr [ebp-3C]
004D371A |. >|mov ecx,dword ptr [ecx]
004D371C |.^>\jmp short 004D36E7
004D371E |> >lea edx,dword ptr [ebp-F8]
004D3724 \.^>jmp 004D1094
......
004D37D4 /$ >push 10 ; /MemSize = 10 (16.)
004D37D6 |. >push 42 ; |Flags = GHND
004D37D8 |. >call dword ptr [<&KERNEL32.GlobalAlloc>] ; \GlobalAlloc
004D37DE |. >mov dword ptr [ebp-2C],eax
004D37E1 |. >mov ecx,dword ptr [ebp-3C]
004D37E4 |. >mov ecx,dword ptr [ecx]
004D37E6 |. >nop
004D37E7 |. >nop
004D37E8 |. >nop
004D37E9 |. >nop
004D37EA |. >mov al,byte ptr [ecx+1]
004D37ED |. >and eax,0FF
004D37F2 |. >mov edx,dword ptr [eax*4+645078]
004D37F9 |. >test edx,edx
004D37FB |. >je short 004D3871
004D37FD |. >mov ax,word ptr [ecx+2]
004D3801 |. >and ecx,0FFFF
004D3807 |. >mov ecx,eax
004D3809 |. >mov eax,dword ptr [edx+2EF2]
004D380F |. >test eax,eax
004D3811 |. >je short 004D3871
004D3813 |. >lea eax,dword ptr [eax+ecx*4]
004D3816 |. >fild word ptr [eax]
004D3818 |. >fdiv dword ptr [61D214]
004D381E |. >mov eax,dword ptr [ebp-110]
004D3824 |. >shl eax,4
004D3827 |. >add eax,00637900 ; ASCII "XXXXX-1"
004D382C |. >add eax,0C
004D382F |. >fld dword ptr [eax]
004D3831 |. >fmulp st(1),st
004D3833 |. >sub esp,8 ; /<%6.2f>
004D3836 |. >fstp qword ptr [esp] ; |
004D3839 |. >push 00637810 ; |format = "%6.2f"
004D383E |. >mov eax,dword ptr [ebp-2C] ; |
004D3841 |. >push dword ptr [eax] ; |s
004D3843 |. >call dword ptr [<&MSVCRTD.sprintf>] ; \sprintf
004D3849 |. >nop
004D384A |. >push 00637870 ; /FileName = "XXXXX.ini"
004D384F |. >mov eax,dword ptr [ebp-2C] ; |
004D3852 |. >push dword ptr [eax] ; |String
004D3854 |. >mov eax,dword ptr [ebp-110] ; |
004D385A |. >shl eax,4 ; |
004D385D |. >add eax,00637900 ; |ASCII "XXXXX-1"
004D3862 |. >push eax ; |Key
004D3863 |. >push 006378A0 ; |Section = "1#XXXXX"
004D3868 |. >call dword ptr [<&kernel32.WritePrivateProf>; \WritePrivateProfileStringA
004D386E |. >mov eax,dword ptr [ebp-2C]
004D3871 |> >push eax ; /hMem
004D3872 |. >call dword ptr [<&KERNEL32.GlobalFree>] ; \GlobalFree
004D3878 |. >add esp,10
004D387B \. >retn
***********************************************************************
赞赏
赞赏
雪币:
留言: