【文章标题】: Sense3保护的绘图辅助软件分析
【文章作者】: Rufus Xu
【作者邮箱】: my_home_page@163.com
【软件名称】: 绘画输出中心
【软件大小】: 2.06M
【下载地址】: 无
【加壳方式】: 无
【保护方式】: 加密狗
【编写语言】: VC++6.0
【使用工具】: OLLDBG
【操作平台】: Windows2000
【软件介绍】: 服装绘图辅助软件(功能:为没有共享功能的绘图仪提供共享,这个软件会设置一个共享目录,并监测目录内的文件有没有发生变化,其他的客户机把绘好的图通过网络放入共享的文件夹,程序会自动检测并将图输出到绘图仪。)
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
Sense3的话题比较多,很多前辈都做了比较细致的教程,紫竹 大侠的《深思3乱弹》系列给了我很大的启发,特别是系列6中的对狗内代码的猜解部分,特别感谢 紫竹 大侠.
废话不多说,进入正题:
辅助工作就不多说了,用IDA分析,导出MAP,以便在OD分析时使用。
程序无狗运行,工具栏上的输出按钮是灰色的,不能使用。用OD载入,对读狗的地方下断:bpx CreateFileA.
F9运行,断下:
004279DE >|> \6A 00 PUSH 0 ; /loc_4279DE; Case 2 of switch 004279B7
004279E0 |. 6A 00 PUSH 0 ; |Attributes = 0
004279E2 |. 6A 03 PUSH 3 ; |Mode = OPEN_EXISTING
004279E4 |. 6A 00 PUSH 0 ; |pSecurity = NULL
004279E6 |. 6A 01 PUSH 1 ; |ShareMode = FILE_SHARE_READ
004279E8 |. 68 00000080 PUSH 80000000 ; |Access = GENERIC_READ
004279ED |. 68 30E34500 PUSH PlotSV.0045E330 ; |\\.\sense3dev
004279F2 |. FF15 B0224500 CALL DWORD PTR DS:[<&KERNEL32.CreateFile>; \CreateFileA
004279F8 |. 83F8 FF CMP EAX,-1
004279FB |. 75 18 JNZ SHORT <PlotSV.loc_427A15>
004279FD |. 8B8424 980000>MOV EAX,DWORD PTR SS:[ESP+98]
00427A04 |. 66:C740 5A 08>MOV WORD PTR DS:[EAX+5A],8
00427A0A |. 66:B8 0100 MOV AX,1
00427A0E |. 81C4 94000000 ADD ESP,94
00427A14 |. C3 RETN
运行到返回:
00427C46 >|> \66:81FF FF01 CMP DI,1FF ; loc_427C46
00427C4B |.^ 76 DF JBE SHORT <PlotSV.loc_427C2C>
00427C4D >|> 66:85C0 TEST AX,AX ; loc_427C4D
00427C50 |. 75 23 JNZ SHORT <PlotSV.loc_427C75>
00427C52 |. 56 PUSH ESI
00427C53 |. E8 28FDFFFF CALL <PlotSV.sub_427980>
00427C58 |. 83C4 04 ADD ESP,4 //返回到这
00427C5B |. 66:85C0 TEST AX,AX
上下看看,没有有用的信息,再运行到返回。(主要是找SENSE3DATA结构赋值的地方)
00427924 |. /7E 3E JLE SHORT <PlotSV.loc_427964>
00427926 >|> |B9 18000000 /MOV ECX,18 ; loc_427926
0042792B |. |8D7424 18 |LEA ESI,DWORD PTR SS:[ESP+18]
0042792F |. |8BFB |MOV EDI,EBX
00427931 |. |6A 01 |PUSH 1
00427933 |. |F3:A5 |REP MOVS DWORD PTR ES:[EDI],DWORD PTR D>
00427935 |. |53 |PUSH EBX
00427936 |. |E8 75020000 |CALL <PlotSV.sub_427BB0>
0042793B |. |66:8B13 |MOV DX,WORD PTR DS:[EBX] //返回到这
0042793E |. |83C4 08 |ADD ESP,8
00427941 |. |85ED |TEST EBP,EBP
00427943 |. |66:8915 34124>|MOV WORD PTR DS:[461234],DX
0042794A |. |75 18 |JNZ SHORT <PlotSV.loc_427964>
0042794C |. |66:813B 8000 |CMP WORD PTR DS:[EBX],80
00427951 |. |72 11 |JB SHORT <PlotSV.loc_427964>
00427953 |. |8B4424 10 |MOV EAX,DWORD PTR SS:[ESP+10]
00427957 |. |8B4C24 14 |MOV ECX,DWORD PTR SS:[ESP+14]
0042795B |. |40 |INC EAX
0042795C |. |3BC1 |CMP EAX,ECX
0042795E |. |894424 10 |MOV DWORD PTR SS:[ESP+10],EAX
00427962 |.^|7C C2 \JL SHORT <PlotSV.loc_427926>
上下看看,没有有用的信息,再运行到返回。(主要是找SENSE3DATA结构赋值的地方)
00427870 >/$ 83EC 60 SUB ESP,60 ; sub_427870
00427873 |. 33C0 XOR EAX,EAX
00427875 |. 66:C74424 02 >MOV WORD PTR SS:[ESP+2],0FFFF
0042787C |. 66:894424 04 MOV WORD PTR SS:[ESP+4],AX
00427881 |. 66:894424 06 MOV WORD PTR SS:[ESP+6],AX
00427886 |. 66:894424 08 MOV WORD PTR SS:[ESP+8],AX
0042788B |. 8D4424 00 LEA EAX,DWORD PTR SS:[ESP]
0042788F |. 50 PUSH EAX ; /Arg1
00427890 |. E8 2B000000 CALL <PlotSV.sub_4278C0> ; \PlotSV.004278C0
00427895 |. 66:8B4424 00 MOV AX,WORD PTR SS:[ESP] //返回到这
0042789A |. 66:3D 8000 CMP AX,80
0042789E |. 74 0C JE SHORT <PlotSV.loc_4278AC>
004278A0 |. 66:3D 8B00 CMP AX,8B
004278A4 |. 74 06 JE SHORT <PlotSV.loc_4278AC>
004278A6 |. 33C0 XOR EAX,EAX
004278A8 |. 83C4 60 ADD ESP,60
004278AB |. C3 RETN
004278AC >|> B8 01000000 MOV EAX,1 ; loc_4278AC
004278B1 |. 83C4 60 ADD ESP,60
004278B4 \. C3 RETN
有点像,但是不是,因为读狗密码不可能都是0。事实上拿SDK中提供的测试工具验证过不是0。
继续返回:
004277CA |. /75 07 JNZ SHORT <PlotSV.loc_4277D3>
004277CC |. |800D 2C124600>OR BYTE PTR DS:[46122C],2
004277D3 >|> \E8 98000000 CALL <PlotSV.sub_427870> ; loc_4277D3; Case 1 of switch 0042779A
004277D8 |. 85C0 TEST EAX,EAX //返回到这 ; //返回到这
上下看看,没有有用的信息,再运行到返回。(主要是找SENSE3DATA结构赋值的地方)
004277F0 > A1 3C124600 MOV EAX,DWORD PTR DS:[46123C] ; sub_4277F0
004277F5 85C0 TEST EAX,EAX
004277F7 75 0F JNZ SHORT <PlotSV.loc_427808>
004277F9 E8 12FFFFFF CALL <PlotSV.sub_427710> ; Sense3.RefreshDeviceList
004277FE |. C705 3C124600>MOV DWORD PTR DS:[46123C],1 //返回到这
上下看看,没有有用的信息,再运行到返回。(主要是找SENSE3DATA结构赋值的地方)
0041D6C5 |. 894D FC MOV DWORD PTR SS:[EBP-4],ECX
0041D6C8 |. 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4]
0041D6CB |. 66:C740 34 46>MOV WORD PTR DS:[EAX+34],46 //PASS1
0041D6D1 |. 8B4D FC MOV ECX,DWORD PTR SS:[EBP-4]
0041D6D4 |. 66:C741 36 04>MOV WORD PTR DS:[ECX+36],4 //PASS2
0041D6DA |. 8B55 FC MOV EDX,DWORD PTR SS:[EBP-4]
0041D6DD |. 66:C742 38 03>MOV WORD PTR DS:[EDX+38],3 //PASS3
0041D6E3 |. 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4]
0041D6E6 |. 66:C740 32 FF>MOV WORD PTR DS:[EAX+32],0FFFF //读狗功能代码
0041D6EC |. 8B4D FC MOV ECX,DWORD PTR SS:[EBP-4]
0041D6EF |. 83C1 30 ADD ECX,30
0041D6F2 |. 51 PUSH ECX
0041D6F3 |. E8 F8A00000 CALL <PlotSV.sub_4277F0> ; Sense3
0041D6F8 |. 8B55 FC MOV EDX,DWORD PTR SS:[EBP-4] //返回到这 ; PlotSV.00460FD4
哈哈,看到没有,找SENSE3DATA结构赋值的地方了
004277F0就是读狗的函数了,相当于SDK中的SENSE3函数。CALL前面的压栈就是结构地址了,记下这个地址=00461000
以后要用到。我们来到地址004277F0看看,
本地调用来自 sub_41D6C1+32, sub_41D716+17, sub_41D716+40, 0041D79E, sub_41D81D+186, 0041DB0B, sub_41DC52+22
共7处,在这7处下断,整个运行一次程序,每次运行把结构中的数据拷贝出来,发现每处的功能是:
0041D6F3 CALL PlotSV.004277F0 OpenDog1 open
0041D72D CALL PlotSV.004277F0 OpenDog2 open
0041D756 CALL PlotSV.004277F0 OpenDog3 read
0041D79E CALL PlotSV.004277F0 OpenDog4
0041D9A3 CALL PlotSV.004277F0 OpenDog5 read
0041DB0B CALL PlotSV.004277F0 OpenDog6
0041DC74 CALL PlotSV.004277F0 OpenDog7 close
开狗的数据我就不写下来了,我们只看看读狗的数据:
第5处读狗的数据为:
00461004 00 00 0E 00 46 00 04 00 ...F..
0046100C 03 00 04 00 1E 31 00 00 ..1.. ax0=311E,ax1=0,bx0=0,bx1=0
00461014 00 00 00 00 04 00 3C 62 .....<b ax0=623C,ax1=0,bx0=A935,bx1=0
0046101C 00 00 35 A9 00 00 00 00 ..5?...
00461004 00 00 0E 00 46 00 04 00 ...F..
0046100C 03 00 04 00 42 18 00 00 ..B.. ax0=1842,ax1=0,bx0=0,bx1=0
00461014 00 00 00 00 04 00 84 30 .....? ax0=3084,ax1=0,bx0=648C,bx1=0
0046101C 00 00 8C 64 00 00 00 00 ..?....
00461004 00 00 0E 00 46 00 04 00 ...F..
0046100C 03 00 04 00 DC 1B 00 00 ..?.. ax0=1BDC,ax1=0,bx0=0,bx1=0
00461014 00 00 00 00 04 00 B8 37 .....? ax0=37B8,ax1=0,bx0=4539,bx1=0
0046101C 00 00 39 45 00 00 00 00 ..9E....
总共读10次,其他的数据就不写了,有这三组数据足够了。
对照紫竹的教程分析发现,
623C=311E * 2 ,623C+311E=935a(bx0=A935)
3084=1842 * 2 ,3084+1842=c648(bx0=648C)
37B8=1BDC * 2 ,37B8+1BDC=9453(bx0=4539)
规律出来了,呵呵,狗内的代码基本上也就出来了。
第3次读狗的数据为:
00461004 00 00 0A 00 46 00 04 00 ....F..
0046100C 03 00 04 00 25 18 00 00 ..%.. ax0=1825,ax1=0,bx0=0000,bx1=0
00461014 00 00 00 00 04 00 0A D7 ....? ax0=D70A,ax1=0,bx0=0000,bx1=0
0046101C 00 00 00 00 00 00 00 00 .......
00461004 00 00 0A 00 46 00 04 00 ....F..
0046100C 03 00 04 00 25 18 00 00 ..%.. ax0=1825,ax1=0,bx0=0001,bx1=0
00461014 01 00 00 00 04 00 A3 3C ....? ax0=3CA3,ax1=0,bx0=0001,bx1=0
0046101C 00 00 01 00 00 00 00 00 .......
经过多次测试发现,第3次读狗的地方,当bx0=0000时,ax0=D70A,当bx0=0001时,ax0=3CA3是固定的数据
数据有了,狗内的代码也都分析出来了,剩下的就是补丁了,还没有试过给PE增加区段,所以这次就想练练手。
用工具给PE增加一个区段,这部分论坛上有详细的教程,工具操作也比较简单,就不多说了。
我们将004277F0处的第条句语句改成跳转语句,跳到我们才增加的区段开头。
0046C000 C605 04104600 0>MOV BYTE PTR DS:[461004],0 //returnflag=0,表示有狗
0046C007 66:833D 0610460>CMP WORD PTR DS:[461006],0E//第5处读狗的功能代码
0046C00F 74 0F JE SHORT PlotSV_n.0046C020//跳到第5处读狗模拟
0046C011 66:833D 0610460>CMP WORD PTR DS:[461006],0A//第3处的读狗功能代码
0046C019 74 36 JE SHORT PlotSV_n.0046C051//跳到第3处读狗模拟
0046C01B - E9 47B8FBFF JMP PlotSV_n.00427867 //其他的开狗由这里反回
0046C020 50 PUSH EAX
0046C021 53 PUSH EBX
0046C022 52 PUSH EDX
0046C023 66:A1 10104600 MOV AX,WORD PTR DS:[461010]
0046C029 66:8BD0 MOV DX,AX
0046C02C 66:D1E0 SHL AX,1
0046C02F 66:8915 1010460>MOV WORD PTR DS:[461010],DX
0046C036 66:03C2 ADD AX,DX
0046C039 66:BB 0010 MOV BX,1000
0046C03D 66:F7E3 MUL BX
0046C040 66:03C2 ADD AX,DX
0046C043 66:A3 14104600 MOV WORD PTR DS:[461014],AX
0046C049 5A POP EDX
0046C04A 5B POP EBX
0046C04B 58 POP EAX
0046C04C - E9 16B8FBFF JMP PlotSV_n.00427867 //第5处读狗功功能模拟返回
0046C051 66:833D 1410460>CMP WORD PTR DS:[461014],1
0046C059 74 0E JE SHORT PlotSV_n.0046C069
0046C05B 66:C705 1A10460>MOV WORD PTR DS:[46101A],0D70A
0046C064 - E9 FEB7FBFF JMP PlotSV_n.00427867
0046C069 66:C705 1A10460>MOV WORD PTR DS:[46101A],3CA3
0046C072 - E9 F0B7FBFF JMP PlotSV_n.00427867 //第3处读狗功功能模拟返回
改完了,保存,运行,呵呵,可以正常出图了,完美模拟。
--------------------------------------------------------------------------------
【经验总结】
1.熟悉了Sense3的SDK使用.
2.复习了PE文件结构.
3.学会了给PE文件增加区段.
4.学会了在PE文件中增加功能代码实现读狗的模拟.
--------------------------------------------------------------------------------
【版权声明】: 转载请注明作者并保持文章的完整, 谢谢!
2006年08月11日 10:59:09
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)