xx病案统计管理系统 V4.61
第一次碰到加了ASprotect的壳并有自己本身的注册程序,心痒解之。
ASProtect 2.1x SKE -> Alexey Solodovnikov
保护方式:Advanced Import protection
1.脱壳:
定位OEP+IAT
code:地址=00401000 大小=00217000 (2191360.)
最后一次异常:
0102FAA5 C700 EFCA5C85 mov dword ptr ds:[eax],855CCAEF
0102FAAB 67:64:8F06 0000 pop dword ptr fs:[0]
0102FAB1 83C4 04 add esp,4
0102FAB4 83E8 AF sub eax,-51
OEP:
00616C7C 55 push ebp
00616C7D 8BEC mov ebp,esp
00616C7F 83C4 F0 add esp,-10
00616C82 53 push ebx
00616C83 B8 74666100 mov eax,main.00616674
00616C88 E8 2FFDDEFF call main.004069BC
00616C8D 8B1D 54816200 mov ebx,dword ptr ds:[628154] ; main.00629C0C
无stolen oep。
IAT:RVA=6301A0-00630998,SIZE=7F8
00406908 - FF25 70026300 jmp dword ptr ds:[630270] ; kernel32.TlsGetValue
0063019C 00000000
006301A0 00000000
006301A4 77F87BF9 ntdll.RtlDeleteCriticalSection
006301A8 77F89134 ntdll.RtlLeaveCriticalSection
006301AC 77F89103 ntdll.RtlEnterCriticalSection
...
006301F4 B5CCB129 // 好多加密
006301F8 4E33759B
006301FC 77E6E6A9 kernel32.GetProcAddress
00630200 00B5580F
00630204 3BD08651
...
00630954 717185C1 comctl32.ImageList_Destroy
00630958 7171884C comctl32.ImageList_Create
0063095C BFCE6B2A
00630960 00000000
00630964 777C440B winspool.OpenPrinterA
00630968 777C5F7C winspool.EnumPrintersA
0063096C 777C583B winspool.DocumentPropertiesA
00630970 777C4964 winspool.ClosePrinter
00630974 00000000
00630978 27BBEA5D
0063097C 00000000
00630980 CA10037F
00630984 67490C24
00630988 3583A4E8
0063098C C5054AA6
00630990 00000000
00630994 77E69BBA kernel32.MulDiv
00630998 00000000
基本情况已经清楚了,开始patch:
第一次patch前的异常:特征码ASCII "85"
0102EA55 C601 B6 mov byte ptr ds:[ecx],0B6
0102EA58 6323 arpl word ptr ds:[ebx],sp
0102EA5A DEAA B86B9C6B fisubr word ptr ds:[edx+6B9C6BB8]
0102EA60 75 11 jnz short 0102EA73
0102EBF8 68 E8F40201 push 102F4E8 ; ASCII "85"
0102EBFD E8 2A62FEFF call 01014E2C
0102EC02 A1 1C370301 mov eax,dword ptr ds:[103371C]
0102EC07 8B00 mov eax,dword ptr ds:[eax]
0102EC09 E8 0A8CFFFF call 01027818
0102EC0E 84C0 test al,al
0102EC10 75 0A jnz short 0102EC1C
0102EC12 68 E8F40201 push 102F4E8 ; ASCII "85"
搜索:3BF0 75 5E EB 01
010275EC 6933 C08A433B imul esi,dword ptr ds:[ebx],3B438A>
010275F2 3BF0 cmp esi,eax //在此下断
010275F4 75 5E jnz short 01027654
010275F6 EB 01 jmp short 010275F9
下断后观察esi值,注意数据窗口的IAT变化。
eax=B8;esi=B8,6F,6B; 当esi=6F加密,好patch代码:
010275F4 - E9 078A2300 jmp 01260000 // 申请的空间
je 010275F9
cmp esi,06B
je 01027654
mov esi,06B
jmp 01027654
patch后F9运行停在下一个异常,撤销所有修改,在010275F4新建eip。
运行到最后一个异常,定位第二次patch的位置:
搜索:89,45,F0,B8,00,07,00,00
01027188 8945 F0 mov dword ptr ss:[ebp-10],eax
0102718B B8 00070000 mov eax,700
01027190 E8 B7B3FDFF call 0100254C //第二次patch的位置
运行到OEP后往下搜索E8:
00401338 E8 C3ECE700 call 01280000
修改第二次patch的位置:
01027190 - E9 A28E2900 jmp 012C0037 // 申请的空间
patch代码:
BA 00104000 803A E8 75 12 8B42 01 03C2 83C0 05 3D 00002801 75 03 EB 0C 90 42 81FA 00806100 72 E0 EB FE 8915 00012C01 60 FFE2 90 90 90 90 90 90 90 60 B8 A0016300 90 3910 75 20 8B0D 00012C01 C701 FF250000 8941 02 61 90 8B15 00012C01 90 90 90 EB BE 90 90 90 90 83C0 04 3D 98096300 7E D2 EB E3 90 90
012C0000 BA 00104000 mov edx,main.<ModuleEntryPoint> ; CODE 开始
012C0005 803A E8 cmp byte ptr ds:[edx],0E8
012C0008 75 12 jnz short 012C001C
012C000A 8B42 01 mov eax,dword ptr ds:[edx+1]
012C000D 03C2 add eax,edx
012C000F 83C0 05 add eax,5
012C0012 3D 00002801 cmp eax,1280000 ; call xxxxxxxx
012C0017 75 03 jnz short 012C001C
012C0019 EB 0C jmp short 012C0027
012C001B 90 nop
012C001C 42 inc edx
012C001D 81FA 00806100 cmp edx,618000 ; code结束
012C0023 ^ 72 E0 jb short 012C0005
012C0025 - EB FE jmp short 012C0025
012C0027 8915 00012C01 mov dword ptr ds:[12C0100],edx
012C002D 60 pushad
012C002E FFE2 jmp edx
012C0030 90 nop
012C0031 90 nop
012C0032 90 nop
012C0033 90 nop
012C0034 90 nop
012C0035 90 nop
012C0036 90 nop
012C0037 60 pushad
012C0038 B8 A0016300 mov eax,6301A0 ; IAT起始
012C003D 90 nop
012C003E 3910 cmp dword ptr ds:[eax],edx
012C0040 75 20 jnz short 012C0062
012C0042 8B0D 00012C01 mov ecx,dword ptr ds:[12C0100]
012C0048 C701 FF250000 mov dword ptr ds:[ecx],25FF
012C004E 8941 02 mov dword ptr ds:[ecx+2],eax
012C0051 61 popad
012C0052 90 nop
012C0053 8B15 00012C01 mov edx,dword ptr ds:[12C0100]
012C0059 90 nop
012C005A 90 nop
012C005B 90 nop
012C005C ^ EB BE jmp short 012C001C
012C005E 90 nop
012C005F 90 nop
012C0060 90 nop
012C0061 90 nop
012C0062 83C0 04 add eax,4
012C0065 3D 98096300 cmp eax,630998 ; IAT结束
012C006A ^ 7E D2 jle short 012C003E
012C006C ^ EB E3 jmp short 012C0051
012C006E 90 nop
012C006F 90 nop
在012C0000新起eip,F9运行。
lordpe选择进程dump,ImportREC选择进程,OEP=00216C7C,自动搜索,没有无效函数,修复。
运行ok,Borland Delphi 6.0 - 7.0。
2.破解:
获得注册码:
单位名称:MeiLun
负责人:God
机器码:WD-WCAD13523066
注册码:87654321
错误提示:注册码错误。
算法查询:Sha-1,Base64
MessageBoxExA,断下后返回,往上找源头:
005BA0FC 55 push ebp
初始化一串数据:
005BA133 C705 00F76200 0>mov dword ptr ds:[62F700],4
005BA13D C705 04F76200 0>mov dword ptr ds:[62F704],2
005BA147 C705 08F76200 0>mov dword ptr ds:[62F708],5
005BA151 C705 0CF76200 0>mov dword ptr ds:[62F70C],7
005BA15B C705 10F76200 0>mov dword ptr ds:[62F710],8
005BA165 C705 14F76200 0>mov dword ptr ds:[62F714],3
005BA16F C705 18F76200 0>mov dword ptr ds:[62F718],1
005BA179 C705 1CF76200 0>mov dword ptr ds:[62F71C],6
取得机器码与上面的数据相加:
005BA193 C703 01000000 mov dword ptr ds:[ebx],1
005BA199 8D55 F8 lea edx,dword ptr ss:[ebp-8]
005BA19C A1 ECF66200 mov eax,dword ptr ds:[62F6EC]
005BA1A1 E8 E2ECE4FF call dumped_.00408E88 ; 机器码
005BA1A6 8B45 F8 mov eax,dword ptr ss:[ebp-8]
005BA1A9 8B13 mov edx,dword ptr ds:[ebx]
005BA1AB 8A4410 FF mov al,byte ptr ds:[eax+edx-1]
005BA1AF 8B13 mov edx,dword ptr ds:[ebx]
005BA1B1 8882 28F76200 mov byte ptr ds:[edx+62F728],al
005BA1B7 8B03 mov eax,dword ptr ds:[ebx]
005BA1B9 0FB680 28F76200 movzx eax,byte ptr ds:[eax+62F728]
005BA1C0 8B13 mov edx,dword ptr ds:[ebx]
005BA1C2 030495 FCF66200 add eax,dword ptr ds:[edx*4+62F6FC] ; 相加
005BA1C9 8D55 F4 lea edx,dword ptr ss:[ebp-C]
005BA1CC E8 43F1E4FF call dumped_.00409314 ; 转换成十进制
005BA1D1 8B55 F4 mov edx,dword ptr ss:[ebp-C]
005BA1D4 8B03 mov eax,dword ptr ds:[ebx]
005BA1D6 8D0485 34F76200 lea eax,dword ptr ds:[eax*4+62F734]
005BA1DD E8 92A2E4FF call dumped_.00404474
005BA1E2 FF03 inc dword ptr ds:[ebx]
005BA1E4 4E dec esi
005BA1E5 ^ 75 B2 jnz short dumped_.005BA199
参数:
0062F700 04 00 00 00 02 00 00 00 05 00 00 00 07 00 00 00 ............
0062F710 08 00 00 00 03 00 00 00 01 00 00 00 06 00 00 00 ............
0062F720 00 00 00 00 00 00 00 00 00 57 44 2D 57 43 41 44 .........WD-WCAD
0062F730 31 33 35 32 33 30 36 36 34 135230664
顺取机器码,+参数(每次4个字节),得到的值转换成十进制。
总共计算15次?,依次为:
堆栈 ss:[0012F0AC]=010745F4, (ASCII "91") // 8;1 W
堆栈 ss:[0012F0AC]=01076C34, (ASCII "70") // 4;0 D
堆栈 ss:[0012F0AC]=00FC30D4, (ASCII "50") // 3;0 -
堆栈 ss:[0012F0AC]=00FC744C, (ASCII "94") // 1;4 W
堆栈 ss:[0012F0AC]=080FD264, (ASCII "75") // 5;5 C
堆栈 ss:[0012F0AC]=080FD274, (ASCII "68") // 6;8 A
堆栈 ss:[0012F0AC]=080FD284, (ASCII "69") // 2;9 D
堆栈 ss:[0012F0AC]=080FD294, (ASCII "55") // 7;5 1
堆栈 ss:[0012F0AC]=080FD2A4, (ASCII "51") 3
堆栈 ss:[0012F0AC]=080FD2B4, (ASCII "53") 5
堆栈 ss:[0012F0AC]=080CC9B4, (ASCII "759453490") 2
堆栈 ss:[0012F0AC]=07EE4D84, (ASCII "1145127818") 3
堆栈 ss:[0012F0AC]=080D49F8, (ASCII "842347361") 0
堆栈 ss:[0012F0AC]=01025FF4, (ASCII "3551337") 6
堆栈 ss:[0012F0AC]=00FD15A4, (ASCII "17253930") 6
然后有选择的取第2位,如上标注,连接:
005BA2B5 B8 7CF76200 mov eax,dumped_.0062F77C
005BA2BA 8B13 mov edx,dword ptr ds:[ebx]
005BA2BC 8B1495 58F76200 mov edx,dword ptr ds:[edx*4+62F758]
005BA2C3 E8 20A4E4FF call dumped_.004046E8
005BA2C8 FF03 inc dword ptr ds:[ebx]
005BA2CA 833B 09 cmp dword ptr ds:[ebx],9
005BA2CD ^ 75 E6 jnz short dumped_.005BA2B5
得到:49005851
与输入的注册码比较:
005BA2D8 E8 0FFEEAFF call dumped_.0046A0EC ; 取注册码
005BA2DD 8B55 F0 mov edx,dword ptr ss:[ebp-10] ; ZCM
005BA2E0 A1 7CF76200 mov eax,dword ptr ds:[62F77C] ; 49005851
005BA2E5 E8 42A5E4FF call dumped_.0040482C ; 比较
005BA2EA 74 1E je short dumped_.005BA30A
如果这个相等的话提示注册成功,但是没看到写入注册表,所在文件夹也没有相关注册文件,可能写入数据库文件:dataset.mdb
重启后提示注册信息错误:
0012F044 77E180BC /CALL 到 MessageBoxExA 来自 user32.77E180B7
0012F048 002801FE |hOwner = 002801FE ('xx病案统计管理系统',class='TApplication')
0012F04C 0058D7F8 |Text = "注册信息错误 - NO.1"
0012F050 0058D798 |Title = "提示"
0012F054 00000000 |Style = MB_OK|MB_APPLMODAL
0012F058 00000000 \LanguageID = 0 (LANG_NEUTRAL)
返回到:
0058CFD3 E8 7CDFEFFF call dumped_.0048AF54
0058CFD8 837D D8 00 cmp dword ptr ss:[ebp-28],0
0058CFDC 74 1D je short dumped_.0058CFFB
根据W32Dasm查找到源头:
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0058CCC5(C)
|
:0058CCD7 8B06 mov eax, dword ptr [esi]
往下看到:
* Possible StringData Ref from Code Obj ->"单位名称"
* Possible StringData Ref from Code Obj ->"注册码"
* Possible StringData Ref from Code Obj ->"单位负责人"
看到希望了,继续往下,看到读取文件hytj.ini的内容:
0058CE68 B9 28D75800 mov ecx,dumped_.0058D728 ; ASCII "hytj.ini"
0058CE6D E8 BA78E7FF call dumped_.0040472C
0058CE72 8B4D DC mov ecx,dword ptr ss:[ebp-24]
0058CE75 B2 01 mov dl,1
0058CE77 A1 00424400 mov eax,dword ptr ds:[444200]
0058CE7C E8 2F74EBFF call dumped_.004442B0
0058CE81 A3 D4F56200 mov dword ptr ds:[62F5D4],eax
0058CE86 6A 00 push 0
0058CE88 8D45 D8 lea eax,dword ptr ss:[ebp-28]
0058CE8B 50 push eax
0058CE8C B9 3CD75800 mov ecx,dumped_.0058D73C ; ASCII "PKCGH"
0058CE91 BA 4CD75800 mov edx,dumped_.0058D74C ; ASCII "SET"
0058CE96 A1 D4F56200 mov eax,dword ptr ds:[62F5D4]
0058CE9B 8B38 mov edi,dword ptr ds:[eax]
0058CE9D FF17 call dword ptr ds:[edi] ; 读取文件hytj.ini的PKCGH
进入该call:
00444C1C E8 EB21FCFF call <jmp.&kernel32.GetPrivateProfileStringA>
0012E8B8 00444C21 /CALL 到 GetPrivateProfileStringA 来自 dumped_.00444C1C
0012E8BC 0058D74C |Section = "SET" // 读取SET部分
0012E8C0 0058D73C |Key = "PKCGH" // 读取PKCGH段内容
0012E8C4 004048E5 |Default = ""
0012E8C8 0012E8E0 |ReturnBuffer = 0012E8E0
0012E8CC 00000800 |BufSize = 800 (2048.)
0012E8D0 080FD0A4 \IniFileName = "E:\xx病案统计管理系统\hytj.ini"
然后就是判断:
0058CEFC 837D D8 00 cmp dword ptr ss:[ebp-28],0 ; 这个数值哪来的?
0058CF00 74 11 je short dumped_.0058CF13 ; 是否为空?
0058CF02 8B45 D8 mov eax,dword ptr ss:[ebp-28]
0058CF05 8B55 CC mov edx,dword ptr ss:[ebp-34] ; (ASCII "D59AW8fl")
0058CF08 E8 1F79E7FF call dumped_.0040482C ; 比较
0058CF0D 0F84 C5000000 je dumped_.0058CFD8 ; 又一个关键跳转
发现[ebp-28]的内容是空的,往下就提示错误信息1,如果修改这个跳转就会比较[ebp-28]的内容是不是ASCII "D59AW8fl"。
添加注册信息:
打开hytj.ini,内容如下:
[set]
database =database\database.mdb
babase =database\mzba.mdb
ime =王码五笔型输入法86版
datainput=2
的确没有PKCGH的内容,于是添加PKCGH部分,注意对齐:
[set]
database =database\database.mdb
babase =database\mzba.mdb
ime =王码五笔型输入法86版
datainput=2
PKCGH =D59AW8fl
重新加载程序,呵呵,这下[ebp-28]的数据就是:D59AW8fl,然后通过比较,跳过错误信息提示,直接进入程序主界面,注册的菜单变灰,搞定。
注册信息:
单位名称:MeiLun
负责人:God
机器码:WD-WCAD13523066
注册码:49005851
hytj.ini添加:PKCGH =D59AW8fl
后记:
跟踪D59AW8fl如何来的,发现过程非常繁琐,涉及到SHA-1加密,Base64加密,而且还有一段可能是作者自己的加密方法,对注册单位名称&注册码的计算结果进行加密的,循环非常大,但是最后还是得到明码比较。
因此注册信息与单位名称,机器码有关。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)