初步分析
没有多余的处理,直接可以进入对话框处理函数sub_402652(),看一下这个函数
int __cdecl sub_402652(HWND hDlg)
{
int i; // esi
signed __int8 v2; // cl
int v3; // eax
size_t v4; // eax
int v5; // edi
int len; // esi
int v7; // eax
char Result; // [esp+Ch] [ebp-614h]
char v10; // [esp+Dh] [ebp-613h]
__int16 v11; // [esp+109h] [ebp-517h]
char v12; // [esp+10Bh] [ebp-515h]
char pbuf; // [esp+10Ch] [ebp-514h]
char v14; // [esp+10Dh] [ebp-513h]
__int16 v15; // [esp+209h] [ebp-417h]
char v16; // [esp+20Bh] [ebp-415h]
unsigned __int8 pGloalStr; // [esp+20Ch] [ebp-414h]
char v18; // [esp+20Dh] [ebp-413h]
__int16 v19; // [esp+309h] [ebp-317h]
char v20; // [esp+30Bh] [ebp-315h]
CHAR Text; // [esp+30Ch] [ebp-314h]
char v22; // [esp+30Dh] [ebp-313h]
__int16 v23; // [esp+409h] [ebp-217h]
char v24; // [esp+40Bh] [ebp-215h]
char pOut; // [esp+40Ch] [ebp-214h]
char v26; // [esp+40Dh] [ebp-213h]
__int16 v27; // [esp+509h] [ebp-117h]
char v28; // [esp+50Bh] [ebp-115h]
char keyStr[12]; // [esp+50Ch] [ebp-114h]
__int16 v30; // [esp+609h] [ebp-17h]
char v31; // [esp+60Bh] [ebp-15h]
CHAR String; // [esp+60Ch] [ebp-14h]
__int16 v33; // [esp+60Dh] [ebp-13h]
char v34; // [esp+60Fh] [ebp-11h]
int lenOfKeyStr; // [esp+610h] [ebp-10h]
size_t inputKeyLen; // [esp+614h] [ebp-Ch]
char v37; // [esp+61Bh] [ebp-5h]
int v38; // [esp+61Ch] [ebp-4h]
String = 0;
v33 = 0;
v34 = 0;
keyStr[0] = 0;
memset(&keyStr[1], 0, 0xFCu);
v30 = 0;
v31 = 0;
pGloalStr = 0;
memset(&v18, 0, 0xFCu);
v19 = 0;
v20 = 0;
Text = 0;
memset(&v22, 0, 0xFCu);
v23 = 0;
v24 = 0;
GetDlgItemTextA(hDlg, 1000, &String, 3);
lenOfKeyStr = GetDlgItemTextA(hDlg, 1001, keyStr, 0xFF);
initTextBufByType(0, &Text); // init Text -no,wrong.sn
inputKeyLen = 0;
v38 = 0;
if ( lenOfKeyStr < 12 ) // 输入字符串条件:开始不能是AA,第5,11位是V V ,长度大于12
v38 = 1;
if ( keyStr[0] == 'A' && keyStr[1] == 'A' ) // AA开始非法
++v38;
if ( keyStr[5] != 'V' || keyStr[11] != 'V' ) // 5,11位V分割
++v38;
for ( i = 0; i < lenOfKeyStr; ++i )
{
if ( i != 5 && i != 11 )
{
v2 = keyStr[i];
v37 = keyStr[i];
if ( dword_4082EC <= 1 )
{
v3 = *((_WORD *)off_4080E0 + v2) & 0x107;
}
else
{
v3 = _isctype(v2, 0x107);
v2 = v37;
}
if ( !v3 )
{
v38 += 3;
break;
}
v4 = inputKeyLen++; // index
*(&pGloalStr + v4) = v2;
}
}
if ( !v38 )
{
pOut = 0;
memset(&v26, 0, 252u);
v27 = 0;
v28 = 0;
Result = 0;
memset(&v10, 0, 0xFCu);
v11 = 0;
v12 = 0;
pbuf = 0;
memset(&v14, 0, 0xFCu);
v15 = 0;
v16 = 0;
v5 = String;
initBase64String(80, &pbuf, 0x40u); // ABCyVPGHTJKLMNOFQRSIUEWDYZgbc8sfah1jklmnopqret5v0xX9wi234u67dz+/
setBase64Customer(&pbuf);
len = base64Encoder(&pGloalStr, &pOut); // key Base64加密
base64Decoder((unsigned __int8 *)&pOut, &Result, len);// key base64解密
if ( pOut )
{
if ( !memcmp(&Result, &pGloalStr, inputKeyLen) )// base64加密前和解密后相当
{
v7 = sub_4024E1(0x64, v5, (int)&pOut, len);// 0x64,O,加密key ,加密key长度
initTextBufByType(v7, &Text); // v7需要等于2,输入正确结果
}
}
}
MessageBoxA(hDlg, &Text, &Text, 0);
return 0;
}
输入字符合法判断
从函数的前面部分可以知道几个输入key的条件:
1、长度大于12
2、前两位不能是AA
3、5,11位V分割
字符合法性判断完成后,进行字符串整理,将V从字符中去掉。
客制化Base64转换
base64 custom字串“ABCyVPGHTJKLMNOFQRSIUEWDYZgbc8sfah1jklmnopqret5v0xX9wi234u67dz+/”
将输入的key进行Base64加密再解密,加密前和解密后相等。这样看来字串长度是4的倍数了。
关键函数
满足base64转换条件后进入关键函数
v7 = sub_4024E1(0x64, v5, (int)&pOut, len);// 0x64,O,加密key ,加密key长度
initTextBufByType(v7, &Text); // v7需要等于2,输入正确结果
关键函数返回2,输入正确结果。
关键函数分析
关键函数内是大整数运算,我们先看一下大整数的数据结构
BigInt struc{
int sing //符号
int len //数据长度
int* pData //指向数据
}
好了,我们进入关键函数看看
int __cdecl sub_4024E1(int const0x64, int charO, int pEnInputKeyStr, int enKeyStrLen)
{
signed int v4; // ebx
int *buf_1; // edi
int pbuf; // [esp+Ch] [ebp-1C0h]
int buf[99]; // [esp+10h] [ebp-1BCh]
BigInt bigData; // [esp+19Ch] [ebp-30h]
BigInt bigIntKey; // [esp+1A8h] [ebp-24h]
BigInt ret; // [esp+1B4h] [ebp-18h]
BigInt p; // [esp+1C0h] [ebp-Ch]
signed int b; // [esp+1D4h] [ebp+8h]
int bingGo; // [esp+1E0h] [ebp+14h]
pbuf = 0;
memset(buf, 0, sizeof(buf));
b = sub_40243F(const0x64, &pbuf); // 产生多素数数组[3,5,7....0x47]
newBigInt(&ret);
newBigInt(&bigData);
setBigInt(&ret, 0); // new String
setBigInt(&bigIntKey, 0);
v4 = 1;
setBigInt(&p, 1);
setBigInt(&bigData, pbuf);
data2BigInt(&bigIntKey, pEnInputKeyStr, enKeyStrLen);// 将输入的key转换位大整数存储
bingGo = getDataFormBigData(&ret);
if ( b > 1 )
{
buf_1 = buf;
while ( *buf_1 != charO )
{
if ( *buf_1 )
createP((int)&p, (int)&p, *buf_1); // 多素数相乘,得到p=0x41cd66acc237b22681a18067
++v4;
++buf_1;
if ( v4 >= b )
goto LABEL_9;
}
b = buf[v4]; // 0x53
}
LABEL_9:
if ( checkBigInt(&bigIntKey, &bigData) >= 0 && checkBigInt(&bigIntKey, &p) <= 0 )// 2<key<p
{
quick_Mod(&ret, &bigIntKey, b, &p); // 快速幂取模==2(2=key^0x53mod(p))
if ( checkBigInt(&ret, &bigData) >= 0 && checkBigInt(&ret, &p) <= 0 )
bingGo = getDataFormBigData(&ret);
}
StringFree((int)&ret);
StringFree((int)&bigData);
return bingGo;
}
这里是多素数相乘,得到p
createP((int)&p, (int)&p, *buf_1); // 多素数相乘,得到p=0x41cd66acc237b22681a18067
核心算法是快速幂取模,取模后的值为2.
2=key^0x53mod(p)
逆结果
多素数RSA密钥产生算法如下:
1.生成k个素数p1, p2, …, pk
2.求k个素数的乘积n=∏pi, i=1,2,…,k
3.求Euler函数值φ(n)=∏(pi-1)
4.选择指数e, 使得gcd(e,φ(n))=1
5.求指数d=e-1 mod φ(n)
6.输出公钥(e,n)和私钥(d,n)
多素数RSA 加密和解密算法与普通RSA的相同:
加密 c=me mod n
解密 m=cd mod n
现在我们已经知道
1、多素数数组[3,5,7....0x47]
2、多素数乘机0x41cd66acc237b22681a18067
3、φ(n)phi =((3-1)(5-1)10D19B3AB2BBDB0940000000..*(0x47-1))0x10D19B3AB2BBDB0940000000
4 、e=0x53
可以求出d= 0x6afde1a6c132be7eb2e43db
那么明文=2^0x6afde1a6c132be7eb2e43db Mod(0x41cd66acc237b22681a18067)==1555D30F38B0DBCAEC83C0F9
BASE64转换后为PEDIy9102dreadyu
以上计算可以使用该题作者在看雪上的工具,很方便。
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法
最后于 2019-3-24 12:40
被ODPan编辑
,原因: