-
-
[原创]PEdiy RoboForm2Go 密码管理软件
-
发表于: 2014-3-9 09:09 5134
-
【文章标题】: PEdiy RoboForm2Go 密码管理软件
【文章作者】: 小Q
【作者邮箱】: qyc5@yahoo.com.cn
【作者主页】: http://www.hookdll.com
【作者QQ号】: no
【软件名称】: RoboForm2Go
【软件大小】: 2m多
【下载地址】: http://www.roboform.com/cn/pass2go.html
【加壳方式】: 无
【保护方式】: 无
【编写语言】: 未知
【使用工具】: OD与PE工具
【操作平台】: Windows 8.1 64bit and xp 32bit test
【软件介绍】: RoboForm2Go是目前世界上最安全实用的密码管理软件
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
3年多了,结婚来都没写过文章了,在工作后抽时间看了下软件并写下了这文章,作下记录,自己也是非常喜欢PEDIY,呵呵,大牛们可以直接略过。。。。。
一直在使用的密码管理软件,非常好用,有那么一天在国外网站发现了PC版的破解,但是就是没U盘版的,自己经常要换电脑使用,U盘到处插!这软件自然就好用了!
软件安装后,分析发现只要用破解后的roboform.dll和roboform-x64.dll在软件解压文件到缓存运行前替换掉这2个文件的话就可以解决问题!运行后就是破解好的!
一开始时想写个DLL完成这个过程的,可是在Windows 8.1 64bit运行出问题,后决定PE里DIY写代码,这样又省了挂一个DLL,可是PEDIY软件要解决的问题非常多!
1.要先获取roboform.dll和roboform-x64.dll所在盘的位置,这个好解决!用PEB找。。。
2.要复制到缓存,地址那么长!!汗,只有wsprintfW能解决问题!
3.最后用CopyFileW进行复制!
然后大问题来了,这软件要运行在32跟64位系统用的,保证兼容是个大问题!这API的获取可也是这大问题,还好可以利用0day知识里的Shellcode代码去动态获取API,呵呵,有些代码是抄的
大体过程:
在程序准备执行时堆栈:
0106FC00 7630495D 返回到 kernel32.7630495D--->这里是中一个调用返回
0106FC04 7E8F5000
0106FC08 /0106FC4C
不说这么多了,看代码吧
第一处Patch
005071D8 > $ E8 C4B40000 CALL Portable.005126A1---> JMP Portable.00DE7961 ; PE开始执行的地方,看堆栈(上),返回在kernel32.dll的一个函数调用上
005071DD .^ E9 17FEFFFF JMP Portable.00506FF9
005071E2 CC INT3
005071E3 CC INT3
005071E4 CC INT3
005071E5 CC INT3
005071E6 CC INT3
////////////////////////////////子函数////////////////////////////////////////////////////////////////////////
00DE7900 /$ 33C0 /XOR EAX, EAX
00DE7902 |. AC |LODS BYTE PTR DS:[ESI] ; LODS到CopyFileW和LoadLibraryA字符串头
00DE7903 |. 85C0 |TEST EAX, EAX ; 0就是找到
00DE7905 |.^ 75 F9 |JNZ SHORT Portable.00DE7900
00DE7907 |. 51 |PUSH ECX
00DE7908 |. 52 |PUSH EDX
00DE7909 |. 56 |PUSH ESI
00DE790A |. 53 |PUSH EBX
00DE790B |. FFD2 |CALL NEAR EDX
00DE790D |. 5A |POP EDX
00DE790E |. 59 |POP ECX
00DE790F |. AB |STOS DWORD PTR ES:[EDI] ; 存到 >ASCII"GetProcAddress"开始的地方
00DE7910 |.^ E2 EE \LOOPD SHORT Portable.00DE7900
00DE7912 |. 33C0 XOR EAX, EAX
00DE7914 \. C3 RETN
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
00DE7915 . 47 65 74 50 7>ASCII "GetProcAddress",0 ------------>等下找到的API调用会存到此处!
00DE7924 . 43 6F 70 79 4>ASCII "CopyFileW",0 -------------->复制文件用的字符串
00DE792E . 4C 6F 61 64 4>ASCII "LoadLibraryA",0 -------------->用这个
00DE793B . 75 73 65 72 3>ASCII "user32.dll",0 -------------->和这个
00DE7946 . 77 73 70 72 6>ASCII "wsprintfW",0 -------------->生出wsprintfW
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
00DE7950 90 NOP
00DE7951 . E8 00000000 CALL Portable.00DE7956 ; 重定位
00DE7956 $ 58 POP EAX
00DE7957 . 83E8 41 SUB EAX, 0x41 ; 加41的00DE7915是存API地址的地方
00DE795A . 50 PUSH EAX
00DE795B .- E9 9B5A0B00 JMP Portable.00E9D3FB
00DE7960 90 NOP
//////////////////////////////////JMP Portable.00DE7961/////////////////////////////////////////////////////////////
00DE7961 > 60 PUSHAD ; 保存下寄存器
00DE7962 . FF7424 20 PUSH DWORD PTR SS:[ESP+0x20] ; 向堆下面取回:返回到 kernel32.7630495D
00DE7966 . 5A POP EDX
00DE7967 > 66:813A 4D5A CMP WORD PTR DS:[EDX], 0x5A4D ; 比较PE头
00DE796C . 74 06 JE SHORT Portable.00DE7974 ; -------------->kernel32.dll基地址找到后跳走
00DE796E . 4A DEC EDX
00DE796F . 66:31D2 XOR DX, DX
00DE7972 .^ EB F3 JMP SHORT Portable.00DE7967
00DE7974 > E8 00000000 CALL Portable.00DE7979 ; 重定位
00DE7979 $ 58 POP EAX
00DE797A . 83E8 64 SUB EAX, 0x64 ; 指向 字符串>ASCII "GetProcAddress",0
00DE797D . 92 XCHG EAX, EDX ; 2个寄存器值交换下
00DE797E . 8BD8 MOV EBX, EAX ; 找到的 kernel32 基地址存入EBX
00DE7980 . 8B73 3C MOV ESI, DWORD PTR DS:[EBX+0x3C] ; kernel32.dll的PE头相对MZ的偏移
00DE7983 . 8B7433 78 MOV ESI, DWORD PTR DS:[EBX+ESI+0x78] ; 输出表地址
00DE7987 . 03F3 ADD ESI, EBX ; 转化成VA,记住esi=输出表VA
00DE7989 . 8B7E 20 MOV EDI, DWORD PTR DS:[ESI+0x20] ; AddressOfNames
00DE798C . 03FB ADD EDI, EBX ; 记住edi=AddressOfNames数组地址
00DE798E . 8B4E 14 MOV ECX, DWORD PTR DS:[ESI+0x14] ; NumberOfFunctions
00DE7991 . 33ED XOR EBP, EBP
00DE7993 . 56 PUSH ESI
00DE7994 > 57 PUSH EDI
00DE7995 . 51 PUSH ECX
00DE7996 . 8B3F MOV EDI, DWORD PTR DS:[EDI] ; 首个Name的VA
00DE7998 . 03FB ADD EDI, EBX
00DE799A . 8BF2 MOV ESI, EDX
00DE799C . 6A 0E PUSH 0xE
00DE799E . 59 POP ECX
00DE799F . F3:A6 REPE CMPS BYTE PTR ES:[EDI], BYTE PTR DS:[ESI] ; 比较
00DE79A1 . 74 08 JE SHORT Portable.00DE79AB ; 如果找到就跳走
00DE79A3 . 59 POP ECX
00DE79A4 . 5F POP EDI
00DE79A5 . 83C7 04 ADD EDI, 0x4
00DE79A8 . 45 INC EBP
00DE79A9 .^ E2 E9 LOOPD SHORT Portable.00DE7994 ; 循环直到找到GetProcAddress
00DE79AB > 59 POP ECX
00DE79AC . 5F POP EDI
00DE79AD . 5E POP ESI
00DE79AE . 8BCD MOV ECX, EBP
00DE79B0 . 8B46 24 MOV EAX, DWORD PTR DS:[ESI+0x24]
00DE79B3 . 03C3 ADD EAX, EBX
00DE79B5 . D1E1 SHL ECX, 1
00DE79B7 . 03C1 ADD EAX, ECX
00DE79B9 . 33C9 XOR ECX, ECX
00DE79BB . 66:8B08 MOV CX, WORD PTR DS:[EAX]
00DE79BE . 8B46 1C MOV EAX, DWORD PTR DS:[ESI+0x1C]
00DE79C1 . 03C3 ADD EAX, EBX
00DE79C3 . C1E1 02 SHL ECX, 0x2
00DE79C6 . 03C1 ADD EAX, ECX
00DE79C8 . 8B00 MOV EAX, DWORD PTR DS:[EAX]
00DE79CA . 03C3 ADD EAX, EBX
00DE79CC . 8BFA MOV EDI, EDX
00DE79CE . 8BF7 MOV ESI, EDI
00DE79D0 . 83C6 0E ADD ESI, 0xE
00DE79D3 . 8BD0 MOV EDX, EAX ; GetProcAddress API调用已找到
00DE79D5 . 6A 02 PUSH 0x2 ; 2次调用子函数去
00DE79D7 . 59 POP ECX
00DE79D8 . E8 23FFFFFF CALL Portable.00DE7900 ; 去获取CopyFileW和LoadLibraryA
00DE79DD . 83C6 0D ADD ESI, 0xD
00DE79E0 . 52 PUSH EDX
00DE79E1 . 56 PUSH ESI
00DE79E2 . FF57 FC CALL NEAR DWORD PTR DS:[EDI-0x4] ; 用获取到的kernel32.LoadLibraryA去加载user32.dll获取其基地址
00DE79E5 . 5A POP EDX
00DE79E6 . 6A 01 PUSH 0x1 ; 1次调用
00DE79E8 . 59 POP ECX
00DE79E9 . 93 XCHG EAX, EBX; 要换成user32.dll基地址用GetProcAddress去获取wsprintfW函数调用并存
00DE79EA . E8 11FFFFFF CALL Portable.00DE7900
00DE79EF . 61 POPAD ; 在此有关要调用的函数地址已全部取到了,恢复寄存器
00DE79F0 . E8 ACACF3FF CALL Portable.00D226A1 ; 执行原程序操作
00DE79F5 .^ E9 FFF5F2FF JMP Portable.00D16FF9
/////////////////////////////////////////////////////////////////////////////////////////////
00DE79FA >- E9 B9590B00 JMP Portable.00E9D3B8 ; 下面的0000空间不能用了,跳到此中转还成,也为了方便看代码,去别的空隙吧
00DE79FF 00 DB 00
00DE7A00 00 DB 00
00DE7A01 00 DB 00
00DE7A02 00 DB 00
00DE7A03 00 DB 00
00DE7A04 00 DB 00
00DE7A05 00 DB 00
00DE7A06 00 DB 00
00DE7A07 00 DB 00
00DE7A08 00 DB 00
00DE7A09 00 DB 00
00DE7A0A 00 DB 00
00DE7A0B 00 DB 00
00DE7A0C 00 DB 00
--------------------------------------------------------------------------------------------
第二处Patch
00402DD3 . E8 487C0000 CALL Portable.0040AA20
00402DD8 C645 FC 28 MOV BYTE PTR SS:[EBP-0x4], 0x28----> ; JMP 00DE79FA 此处发现程序已生面缓存地址可去利用
00402DDC C645 FC 26 MOV BYTE PTR SS:[EBP-0x4], 0x26
00402DE0 . 8B8D 70FFFFFF MOV ECX, DWORD PTR SS:[EBP-0x90]
--------------------------------------字串存放处----------------------------------------------
00E9D357 0000 ADD BYTE PTR DS:[EAX], AL
00E9D359 49 DEC ECX
00E9D35A 003A ADD BYTE PTR DS:[EDX], BH
00E9D35C 002F ADD BYTE PTR DS:[EDI], CH
00E9D35E 0072 00 ADD BYTE PTR DS:[EDX], DH
00E9D361 6F OUTS DX, DWORD PTR ES:[EDI]
00E9D362 0062 00 ADD BYTE PTR DS:[EDX], AH
00E9D365 6F OUTS DX, DWORD PTR ES:[EDI]
00E9D366 0066 00 ADD BYTE PTR DS:[ESI], AH
00E9D369 6F OUTS DX, DWORD PTR ES:[EDI]
00E9D36A 0072 00 ADD BYTE PTR DS:[EDX], DH
00E9D36D 6D INS DWORD PTR ES:[EDI], DX
00E9D36E 002E ADD BYTE PTR DS:[ESI], CH
00E9D370 006400 6C ADD BYTE PTR DS:[EAX+EAX+0x6C], AH
00E9D374 006C00 00 ADD BYTE PTR DS:[EAX+EAX], CH
00E9D378 0049 00 ADD BYTE PTR DS:[ECX], CL
00E9D37B 3A00 CMP AL, BYTE PTR DS:[EAX]
00E9D37D 2F DAS
00E9D37E 0072 00 ADD BYTE PTR DS:[EDX], DH
00E9D381 6F OUTS DX, DWORD PTR ES:[EDI]
00E9D382 0062 00 ADD BYTE PTR DS:[EDX], AH
00E9D385 6F OUTS DX, DWORD PTR ES:[EDI]
00E9D386 0066 00 ADD BYTE PTR DS:[ESI], AH
00E9D389 6F OUTS DX, DWORD PTR ES:[EDI]
00E9D38A 0072 00 ADD BYTE PTR DS:[EDX], DH
00E9D38D 6D INS DWORD PTR ES:[EDI], DX
00E9D38E 002D 00780036 ADD BYTE PTR DS:[0x36007800], CH
00E9D394 003400 ADD BYTE PTR DS:[EAX+EAX], DH
00E9D397 2E:006400 6C ADD BYTE PTR CS:[EAX+EAX+0x6C], AH
00E9D39C 006C00 00 ADD BYTE PTR DS:[EAX+EAX], CH
00E9D3A0 0000 ADD BYTE PTR DS:[EAX], AL
00E9D3A2 0025 0073002F ADD BYTE PTR DS:[0x2F007300], AH
00E9D3A8 0025 00730000 ADD BYTE PTR DS:[0x7300], AH
00E9D3AE 0000 ADD BYTE PTR DS:[EAX], AL
00E9D3B0 0000 ADD BYTE PTR DS:[EAX], AL
00E9D3B2 0000 ADD BYTE PTR DS:[EAX], AL
00E9D3B4 0000 ADD BYTE PTR DS:[EAX], AL
00E9D3B6 0000 ADD BYTE PTR DS:[EAX], AL
》》》》》》》
-------------------------代码乱写没优化--------------------------------------------------------------------------
00E9D3B8 60 PUSHAD ; 保存一下寄存器
00E9D3B9 FC CLD
00E9D3BA 33D2 XOR EDX, EDX ; 本来想调用API的,但更本就没必要
00E9D3BC 64:8B15 3000000>MOV EDX, DWORD PTR FS:[0x30] ; 从PEB X30处开始找到程序运行所在要用的盘符
00E9D3C3 8B52 0C MOV EDX, DWORD PTR DS:[EDX+0xC]
00E9D3C6 8B52 14 MOV EDX, DWORD PTR DS:[EDX+0x14]
00E9D3C9 8B72 28 MOV ESI, DWORD PTR DS:[EDX+0x28]
00E9D3CC 83EE 06 SUB ESI, 0x6 ; 加6处就是
00E9D3CF E8 00000000 CALL Portable.00E9D3D4 ; 重定位地址
00E9D3D4 58 POP EAX
00E9D3D5 83E8 7B SUB EAX, 0x7B ; 本地址开始加上7B就是EAX 00E9D359 UNICODE "C:/roboform.dll"
00E9D3D8 8B0E MOV ECX, DWORD PTR DS:[ESI] ; 新盘符存到ECX
00E9D3DA 8908 MOV DWORD PTR DS:[EAX], ECX ; U码,4个字节刚好SMC写入
00E9D3DC 50 PUSH EAX ; 存到堆栈备用
00E9D3DD 83C0 06 ADD EAX, 0x6 ; 减6是roboform.dll字符串
00E9D3E0 50 PUSH EAX ; 存到堆栈备用
00E9D3E1 83C0 1A ADD EAX, 0x1A ; 减1A是EAX 00E9D379 UNICODE "C:/roboform-x64.dll"
00E9D3E4 8908 MOV DWORD PTR DS:[EAX], ECX ; U码,4个字节刚好SMC写入
00E9D3E6 50 PUSH EAX ; 存到堆栈备用
00E9D3E7 83C0 06 ADD EAX, 0x6 ; 减6是roboform-x64.dll字符串
00E9D3EA 50 PUSH EAX ; 存到堆栈备用
00E9D3EB 3E:FF7424 24 PUSH DWORD PTR DS:[ESP+0x24] ; 缓存地址压在栈头 UNICODE "C:/Users/qyc/AppData/Local/Temp/RoboForm"
00E9D3F0 5E POP ESI ; 弹到ESI
00E9D3F1 56 PUSH ESI ; 还是存一份在堆备用吧
00E9D3F2 83C0 24 ADD EAX, 0x24 ; 减24,就是UNICODE "%s/%s",这个是连接字符串要用的
00E9D3F5 50 PUSH EAX ; 也要存到堆栈备用
00E9D3F6 - E9 56A5F4FF JMP Portable.00DE7951 ; 我操,要JMP去存放API的地址调用取得,都怪空隙不足,要JMP,J来M去的
00E9D3FB 3E:FF7424 14 PUSH DWORD PTR DS:[ESP+0x14] ; 开始准备合体,第一个字串入栈堆栈 UNICODE "roboform.dll"
00E9D400 56 PUSH ESI ; ESI还有缓存地址,直接入。。。UNICODE "C:/Users/qyc/AppData/Local/Temp/RoboForm"
00E9D401 FF7424 0C PUSH DWORD PTR SS:[ESP+0xC] ; 第三个连接符。。。入堆栈 UNICODE "%s/%s"
00E9D405 81C6 50010000 ADD ESI, 0x150 ; 我发现缓存地址150的地方有一大遍000可用,但8.1下就不是OOO,但破坏后没事,就入吧
00E9D40B 56 PUSH ESI ; 压入
00E9D40C FF50 08 CALL NEAR DWORD PTR DS:[EAX+0x8] ; 调用 (user32.wsprintfW)合体
00E9D40F 6A 00 PUSH 0x0 ; 压入O,可。。。你知道的
00E9D411 56 PUSH ESI ; NEW新地址
00E9D412 FF7424 30 PUSH DWORD PTR SS:[ESP+0x30] ; 程序下破解好的DLL地址
00E9D416 8B4C24 1C MOV ECX, DWORD PTR SS:[ESP+0x1C]
00E9D41A FF11 CALL NEAR DWORD PTR DS:[ECX] ; 完成复制一个
00E9D41C FF7424 1C PUSH DWORD PTR SS:[ESP+0x1C]
00E9D420 FF7424 0C PUSH DWORD PTR SS:[ESP+0xC]
00E9D424 FF7424 0C PUSH DWORD PTR SS:[ESP+0xC]
00E9D428 56 PUSH ESI
00E9D429 FF7424 20 PUSH DWORD PTR SS:[ESP+0x20]
00E9D42D 5B POP EBX
00E9D42E FF53 08 CALL NEAR DWORD PTR DS:[EBX+0x8] ; 合成64位地址
00E9D431 6A 00 PUSH 0x0
00E9D433 56 PUSH ESI
00E9D434 FF7424 38 PUSH DWORD PTR SS:[ESP+0x38]
00E9D438 FF13 CALL NEAR DWORD PTR DS:[EBX] ; 完成复制动作
00E9D43A 61 POPAD ; 以下动作恢复堆栈弹掉没用的
00E9D43B 58 POP EAX
00E9D43C 58 POP EAX
00E9D43D 58 POP EAX
00E9D43E 58 POP EAX
00E9D43F 58 POP EAX
00E9D440 58 POP EAX
00E9D441 58 POP EAX
00E9D442 61 POPAD ; 还原寄存器
00E9D443 C645 FC 28 MOV BYTE PTR SS:[EBP-0x4], 0x28 ; 原程序动作
00E9D447 C645 FC 26 MOV BYTE PTR SS:[EBP-0x4], 0x26
00E9D44B - E9 9059D7FF JMP Portable.00C12DE0 ; 回去执行
00E9D450 90 NOP
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2014年03月09日 9:06:52
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)