控件加密方式之窥探、模拟
场景
控件:xxxxx.ocx
目的:通过反汇编调试跟踪控件对于密码的加密方式
登录界面如下图,密码框为控件:
工具
OllyDBG_1.10
步骤
1、 使用RUN跟踪等方式找到关键代码位置,如下图:
大家可以看到此处“999999”为输入的密码,06CA75EC函数的目的是对原始密码做3DES加密,密钥固定。
2、 继续运行,如下图
EAX所指向地址存储的是06CA75EC函数输出的数据,即为加密后的值。
3、 继续运行,如下图
EDX中是经过06CA7660函数作用后的数据,这里很容易看出06CA7660函数的作用其实就是将16字节的内存值转换为32字节的字符串。
4、 略过不重要的函数,继续单步到下图:
这里可以看到刚才的32位字符串后面跟着我们输入的验证码,此36字节作为06CA75EC函数的输入参数,此06CA75EC同前,此处又调用了一次。
5、 继续单步,如下图:
EAX所指向地址存储的是06CA75EC函数输出的数据,即为36字节加密后的值。
6、 继续单步,又是06CA7660函数,作用同上,结果如下图
通过抓包我们可以看到,此处f791e866…字符串就是我们要往服务器发送的加密后的密码,至此跟踪结束。
代码模拟
a 所需结构、基础函数:
struct DELSTR
{
// DWORD dw1;
// DWORD dw2;
DWORD dw3;
DWORD dw4;
char sz[40];
};
typedef VOID (*DES)();
CString TranslateChar( IN UCHAR * pSrc,IN int SrcLen )
{
CString sRetC,sTemp;
for( int i = 0 ; i < SrcLen ; i ++ )
{
sTemp.Format("%x",pSrc[i]>>4&0x0f);
sRetC += sTemp.GetAt(0);
sTemp.Format("%x",pSrc[i]&0x0f);
sRetC += sTemp.GetAt(0);
}
return sRetC;
}
b 主程序部分:
HINSTANCE hInst = ::LoadLibrary("C:\\WINDOWS\\Downloaded Program Files\\xxxxx.ocx");
DES DesFun = (DES)((DWORD)hInst + 0x67XXX);
char szDes[40];
CString strDes;
DELSTR delstr;
delstr.dw3 = 0x01; // 引用次数,这里为1
delstr.dw4 = 0x06; // 字符串长度
// 1、加密、转换成字符串
strcpy(delstr.sz, "999999"); // 密码
__asm
{
lea eax, delstr.sz
lea edx, szDes
}
DesFun();
strDes = TranslateChar((UCHAR *)szDes, 16);
// 2、转换过的字符串后面加上验证码
strDes += "HUAG"; // 验证码
// 3、再次加密、转换成字符串
delstr.dw3 = 0x01;
delstr.dw4 = 0x24;
strcpy(delstr.sz, strDes);
__asm
{
lea eax, delstr.sz
lea edx, szDes
}
DesFun();
strDes = TranslateChar((UCHAR *)szDes, 16);
::FreeLibrary(hInst);
注:
1、 安全性起见,此处用户名、密码都是虚拟的,函数地址也以XXX代替。
2、 DesFun函数即为上述06CA75EC函数,此处直接调用OCX中的代码,如花精力弄出密钥,则不需要再调用这个OCX中的代码。
3、 TranslateChar函数功能是将16字节二进制数据转换成32位字符串,相当于原来模块中的06CA7660函数。
4、 DELSTR结构目的是模拟DELPHI中的字符串,此处作为DesFun函数的入参。
5、 因为此控件为DELPHI所写,函数调用采用DELPHI的快速调用约定,故在C++中只能模拟它的调用,这就是你在代码中看到内嵌汇编的原因。