small-q 发表于 2014-3-9 09:14:18

PEdiy RoboForm2Go 密码管理软件

【文章标题】: PEdiy RoboForm2Go 密码管理软件
【文章作者】: 小Q
【作者邮箱】: [email protected]
【作者主页】: 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----> JMPPortable.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:                           ;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:                        ;存到 >ASCII"GetProcAddress"开始的地方
00DE7910|.^ E2 EE         \LOOPD   SHORT Portable.00DE7900
00DE7912|.33C0          XOR   EAX, EAX
00DE7914\.C3            RETN00DE7915   .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      -------------->生出wsprintfW00DE7950      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//////////////////////////////////JMPPortable.00DE7961/////////////////////////////////////////////////////////////
00DE7961   >60            PUSHAD                                             ;保存下寄存器
00DE7962   .FF7424 20   PUSH    DWORD PTR SS:                      ;向堆下面取回:返回到 kernel32.7630495D
00DE7966   .5A            POP   EDX
00DE7967   >66:813A 4D5ACMP   WORD PTR DS:, 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:               ;kernel32.dll的PE头相对MZ的偏移
00DE7983   .8B7433 78   MOV   ESI, DWORD PTR DS:             ;输出表地址
00DE7987   .03F3          ADD   ESI, EBX                                     ;转化成VA,记住esi=输出表VA
00DE7989   .8B7E 20       MOV   EDI, DWORD PTR DS:               ;AddressOfNames
00DE798C   .03FB          ADD   EDI, EBX                                     ;记住edi=AddressOfNames数组地址
00DE798E   .8B4E 14       MOV   ECX, DWORD PTR DS:               ;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:                      ;首个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:, BYTE PTR DS:    ;比较
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:
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:
00DE79BE   .8B46 1C       MOV   EAX, DWORD PTR DS:
00DE79C1   .03C3          ADD   EAX, EBX
00DE79C3   .C1E1 02       SHL   ECX, 0x2
00DE79C6   .03C1          ADD   EAX, ECX
00DE79C8   .8B00          MOV   EAX, DWORD PTR DS:
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:                  ;用获取到的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:, 0x28--------------> ;JMP   00DE79FA 此处发现程序已生面缓存地址可去利用
00402DDC      C645 FC 26    MOV   BYTE PTR SS:, 0x26
00402DE0   .8B8D 70FFFFFF MOV   ECX, DWORD PTR SS:--------------------------------------字串存放处----------------------------------------------
00E9D357    0000            ADD   BYTE PTR DS:, AL
00E9D359    49            DEC   ECX
00E9D35A    003A            ADD   BYTE PTR DS:, BH
00E9D35C    002F            ADD   BYTE PTR DS:, CH
00E9D35E    0072 00         ADD   BYTE PTR DS:, DH
00E9D361    6F            OUTS    DX, DWORD PTR ES:
00E9D362    0062 00         ADD   BYTE PTR DS:, AH
00E9D365    6F            OUTS    DX, DWORD PTR ES:
00E9D366    0066 00         ADD   BYTE PTR DS:, AH
00E9D369    6F            OUTS    DX, DWORD PTR ES:
00E9D36A    0072 00         ADD   BYTE PTR DS:, DH
00E9D36D    6D            INS   DWORD PTR ES:, DX
00E9D36E    002E            ADD   BYTE PTR DS:, CH
00E9D370    006400 6C       ADD   BYTE PTR DS:, AH
00E9D374    006C00 00       ADD   BYTE PTR DS:, CH
00E9D378    0049 00         ADD   BYTE PTR DS:, CL
00E9D37B    3A00            CMP   AL, BYTE PTR DS:
00E9D37D    2F            DAS
00E9D37E    0072 00         ADD   BYTE PTR DS:, DH
00E9D381    6F            OUTS    DX, DWORD PTR ES:
00E9D382    0062 00         ADD   BYTE PTR DS:, AH
00E9D385    6F            OUTS    DX, DWORD PTR ES:
00E9D386    0066 00         ADD   BYTE PTR DS:, AH
00E9D389    6F            OUTS    DX, DWORD PTR ES:
00E9D38A    0072 00         ADD   BYTE PTR DS:, DH
00E9D38D    6D            INS   DWORD PTR ES:, DX
00E9D38E    002D 00780036   ADD   BYTE PTR DS:, CH
00E9D394    003400          ADD   BYTE PTR DS:, DH
00E9D397    2E:006400 6C    ADD   BYTE PTR CS:, AH
00E9D39C    006C00 00       ADD   BYTE PTR DS:, CH
00E9D3A0    0000            ADD   BYTE PTR DS:, AL
00E9D3A2    0025 0073002F   ADD   BYTE PTR DS:, AH
00E9D3A8    0025 00730000   ADD   BYTE PTR DS:, AH
00E9D3AE    0000            ADD   BYTE PTR DS:, AL
00E9D3B0    0000            ADD   BYTE PTR DS:, AL
00E9D3B2    0000            ADD   BYTE PTR DS:, AL
00E9D3B4    0000            ADD   BYTE PTR DS:, AL
00E9D3B6    0000            ADD   BYTE PTR DS:, AL-------------------------代码乱写没优化--------------------------------------------------------------------------
00E9D3B8    60            PUSHAD                                  ; 保存一下寄存器
00E9D3B9    FC            CLD
00E9D3BA    33D2            XOR   EDX, EDX                        ; 本来想调用API的,但更本就没必要
00E9D3BC    64:8B15 3000000>MOV   EDX, DWORD PTR FS:      ; 从PEB X30处开始找到程序运行所在要用的盘符
00E9D3C3    8B52 0C         MOV   EDX, DWORD PTR DS:
00E9D3C6    8B52 14         MOV   EDX, DWORD PTR DS:
00E9D3C9    8B72 28         MOV   ESI, DWORD PTR DS:
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:         ; 新盘符存到ECX
00E9D3DA    8908            MOV   DWORD PTR DS:, 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:, 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:         ; 缓存地址压在栈头 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:         ; 开始准备合体,第一个字串入栈堆栈 UNICODE "roboform.dll"
00E9D400    56            PUSH    ESI                           ; ESI还有缓存地址,直接入。。。UNICODE "C:/Users/qyc/AppData/Local/Temp/RoboForm"
00E9D401    FF7424 0C       PUSH    DWORD PTR SS:          ; 第三个连接符。。。入堆栈 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:   ; 调用 (user32.wsprintfW)合体
00E9D40F    6A 00         PUSH    0x0                           ; 压入O,可。。。你知道的
00E9D411    56            PUSH    ESI                           ; NEW新地址
00E9D412    FF7424 30       PUSH    DWORD PTR SS:         ; 程序下破解好的DLL地址
00E9D416    8B4C24 1C       MOV   ECX, DWORD PTR SS:
00E9D41A    FF11            CALL    NEAR DWORD PTR DS:         ; 完成复制一个
00E9D41C    FF7424 1C       PUSH    DWORD PTR SS:
00E9D420    FF7424 0C       PUSH    DWORD PTR SS:
00E9D424    FF7424 0C       PUSH    DWORD PTR SS:
00E9D428    56            PUSH    ESI
00E9D429    FF7424 20       PUSH    DWORD PTR SS:
00E9D42D    5B            POP   EBX
00E9D42E    FF53 08         CALL    NEAR DWORD PTR DS:   ; 合成64位地址
00E9D431    6A 00         PUSH    0x0
00E9D433    56            PUSH    ESI
00E9D434    FF7424 38       PUSH    DWORD PTR SS:
00E9D438    FF13            CALL    NEAR DWORD PTR DS:         ; 完成复制动作
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:, 0x28   ; 原程序动作
00E9D447    C645 FC 26      MOV   BYTE PTR SS:, 0x26
00E9D44B- E9 9059D7FF   JMP   Portable.00C12DE0               ; 回去执行
00E9D450    90            NOP--------------------------------------------------------------------------------
【版权声明】: 本文原创于PYG论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2014年03月08日 20:35:04   

ochchina 发表于 2014-3-9 10:47:51

最好弄个附件。小菜看懂还是有点难度- - {:loveliness:}

Nisy 发表于 2014-3-9 12:09:55

膜拜

wkxq 发表于 2014-3-9 16:04:17

最好有视频教程

cjteam 发表于 2014-3-9 20:26:17

强通过下载文件调试 可以学到不少 感谢好文章

月之精灵 发表于 2014-3-10 18:11:22

强悍,学习了

飘云 发表于 2014-3-11 21:56:45

哈哈,shellcode。。

小试锋芒 发表于 2014-3-11 23:03:19

小Q的大作,前来学习!

mumuhua 发表于 2016-4-15 06:48:17

谢谢楼主 真厉害啊

zjpqapyg 发表于 2016-5-6 17:23:08

花费电话费fdfdfa
页: [1] 2
查看完整版本: PEdiy RoboForm2Go 密码管理软件