记一次软件DIY——联创上网助手添加余额查询功能
【文章作者】: Eddy【作者邮箱】: [email protected]
【作者主页】: http://www.rrgod.com
前些日子写了个小软件,可以查询江苏电信上网卡的余额:http://www.rrgod.com/post/320.html
后来想想为何不直接将其集成到上网助手软件的右键功能菜单中,于是开工……
这是最终效果,没修改前是没有“余额查询”这一项的
http://online.cumt.edu.cn/discuz/attachments/month_1001/1001161101c06e50dd75da8b3d.jpg
首先说下,这个上网助手的密码保存,用了个很简单的加密算法,海风月影大哥很早以前也分析过,我这再简单说下:
软件是加的AsProtect的壳,用脚本就能脱。找到启动时读取加密后密码信息的关键处,如下:
004022A5 8A044E MOV AL,BYTE PTR DS: ; 取1位送al
004022A8 3C 39 CMP AL,39 ; 与39比较
004022AA 0FBEC0 MOVSX EAX,AL
004022AD 7F 05 JG SHORT 004022B4 ; 大于跳走
004022AF 83E8 30 SUB EAX,30 ; -30
004022B2 EB 03 JMP SHORT 004022B7
004022B4 83E8 57 SUB EAX,57 ; -57
004022B7 8A544E 01 MOV DL,BYTE PTR DS: ; 接下来1位
004022BB C0E0 04 SHL AL,4 ; 移位
004022BE 80FA 39 CMP DL,39 ; 同上
004022C1 88440C 1C MOV BYTE PTR SS:,AL
004022C5 0FBED2 MOVSX EDX,DL
004022C8 7F 05 JG SHORT 004022CF
004022CA 83EA 30 SUB EDX,30
004022CD EB 03 JMP SHORT 004022D2
004022CF 83EA 57 SUB EDX,57
004022D2 8BD9 MOV EBX,ECX
004022D4 83E3 0F AND EBX,0F
004022D7 0AC2 OR AL,DL ; 相加
004022D9 32441C 0C XOR AL,BYTE PTR SS: ; 按位与MD5值XOR
004022DD 88440C 1C MOV BYTE PTR SS:,AL ; 结果保存
我在查询余额的软件中,用VB还原了这一小段算法,如下:
'-------------------密码还原----------------------
strMD5 = DigestStrToHexStr(Text1) '获取账户的MD5值
strName = Mid(strName, 1, InStr(strName, "@") - 1)
Text1.Text = strName
For I = 1 To Len(Text2) Step 2
temp = Asc(Mid(Text2, I, 1))
If temp > 57 Then
temp = temp - 87
Else
temp = temp - 48
End If
temp = temp * 16
temp2 = Asc(Mid(Text2, I + 1, 1))
If temp2 > 57 Then
temp2 = temp2 - 87
Else
temp2 = temp2 - 48
End If
temp = temp + temp2
temp = temp Xor CInt("&H" & Mid(strMD5, I, 2))
strResult = strResult & Chr(temp)
Next I
'-------------------------------------------------
好,接下来讨论怎么在托盘右键弹出菜单中加入余额查询这一功能。
基本思路就是调用ShellExecuteA函数来执行写好的江苏电信上网卡余额查询.exe软件。分三步走:
(1)添加菜单
这个用资源工具就可以轻松实现,我是用Resource Hacker添加的,添加后记住资源ID,我这里用的是100(H64).
(2)寻找原软件的消息循环
这个主要从菜单中的一些已有的功能入手,比如有关于上网助手这一项,点击后弹出一个对话框。那么我们可以对其下断(bp DialogBoxParamA),这样就能找到消息循环,如下:
00406C39 FF15 F4514100 CALL DWORD PTR DS:[<&user32.TrackPopupMenu>] ; user32.TrackPopupMenu
00406C3F 3D 0D800000 CMP EAX,800D
00406C44 0F8F B8000000 JG 00406D02
00406C4A 74 60 JE SHORT 00406CAC
00406C4C- E9 B01F0100 JMP 00418C01 ; 关于
00406C51 48 DEC EAX
00406C52 74 2C JE SHORT 00406C80
00406C54 2D A27F0000 SUB EAX,7FA2
00406C59 0F85 30010000 JNZ 00406D8F
00406C5F 833D 3CB24100 0>CMP DWORD PTR DS:,1
00406C66 6A 09 PUSH 9
00406C68 0F84 DC000000 JE 00406D4A
00406C6E 8B15 5CB14100 MOV EDX,DWORD PTR DS:
00406C74 52 PUSH EDX
00406C75 FF15 64524100 CALL DWORD PTR DS:[<&user32.ShowWindow>] ; user32.ShowWindow
00406C7B 5E POP ESI
00406C7C 83C4 08 ADD ESP,8
00406C7F C3 RETN
00406C80 C605 50B64100 0>MOV BYTE PTR DS:,0
00406C87 E8 64FEFFFF CALL 00406AF0
00406C8C 5E POP ESI
00406C8D 83C4 08 ADD ESP,8
00406C90 C3 RETN
00406C91 A1 04B24100 MOV EAX,DWORD PTR DS:
00406C96 6A 00 PUSH 0
00406C98 68 A01C4000 PUSH 00401CA0
00406C9D 56 PUSH ESI
00406C9E 6A 72 PUSH 72
00406CA0 50 PUSH EAX
00406CA1 FF15 08524100 CALL DWORD PTR DS:[<&user32.DialogBoxParamA>] ; user32.DialogBoxParamA
其中00406C4C处的代码是我修改后的代码,我们就是要从此处跳到处理我们自己的消息代码那去。
(3)添加功能代码
从00406C4C楚JMP到00418C01(这个地址你可以任选一块空地),我们就在此实现功能代码,如下:
00418C01 83F8 64 CMP EAX,64 ; 比较是不是余额查询消息?
00418C04 75 1A JNZ SHORT 00418C20
00418C06 60 PUSHAD
00418C07 6A 01 PUSH 1
00418C09 6A 00 PUSH 0
00418C0B 6A 00 PUSH 0
00418C0D 68 588C4100 PUSH 00418C58 ;这个地址存放要调用软件的路径
00418C12 68 9C8C4100 PUSH 00418C9C ; ASCII "open"
00418C17 6A 00 PUSH 0
00418C19 FF15 B0514100 CALL DWORD PTR DS:[<&shell32.ShellExecuteA>] ; shell32.ShellExecuteA
00418C1F 61 POPAD
00418C20 83E8 68 SUB EAX,68
00418C23- 0F84 68E0FEFF JE 00406C91
00418C29- E9 23E0FEFF JMP 00406C51 ; 跳回正常流程
ShellExecuteA函数的调用地址我们可以用LordPE查看原软件的输入表来得知,也可以在OD中Ctrl+N来找地址。有人问要是没这个函数怎么办,答案是:你可以用LordPE在它的输入表中添加这个函数。
关于ShellExecuteA函数的调用格式,MSDN上有,在这也贴一份,方便大家学习:
HINSTANCE ShellExecute(
HWND hwnd, // handle to parent window
LPCTSTR lpOperation, // pointer to string that specifies operation to perform
LPCTSTR lpFile, // pointer to filename or folder name string
LPCTSTR lpParameters, // pointer to string that specifies executable-file parameters
LPCTSTR lpDirectory, // pointer to string that specifies default directory
INT nShowCmd // whether file is shown when opened
);
安装对应的参数Push代码就可以了,注意顺序。
保存下修改后的文件,这样一次DIY就OK了^_
-------------------------------------
转载请注明作者并保持文章的完整, 谢谢!
2010年1月19日 17:33:25 看的晕头转向 高手,绝对是高手。。。/:good /:good
回复 3# walili 的帖子
向高手学习 /:001 强悍 PE DIY 楼主分析的很牛X 认真学习中 ~!!!!!!!!!!!!! 楼主好厉害啊。
页:
[1]