新手一枚,如有错误(不足)请指正,谢谢!!
题目链接:BUUCTF-re-刮开有奖
参考资料:
1. WinMain函数参数介绍
2. Base64编码/解码
IDA32位载入,只有WinMain函数
查看DialogFunc参数
BOOL __stdcall DialogFunc(HWND hDlg, UINT a2, WPARAM a3, LPARAM a4)
{
const char *v4; // esi
const char *v5; // edi
int v7[11]; // [esp+8h] [ebp-20030h]
CHAR String[9]; // [esp+34h] [ebp-20004h]
CHAR v9[3]; // [esp+10034h] [ebp-10004h]
if ( a2 == 272 )
return 1;
if ( a2 != 273 )
return 0; //
// a2 = 273
if ( a3 == 1001 ) // a3 = 1001
{
memset(String, 0, 0xFFFFu); // 给string清零
GetDlgItemTextA(hDlg, 1000, String, 0xFFFF);// 获取对话框文本,然后赋值给string
if ( strlen(String) == 8 ) // string的长度要为8
{
v7[0] = 90;
v7[1] = 74;
v7[2] = 83;
v7[3] = 69;
v7[4] = 67;
v7[5] = 97;
v7[6] = 78;
v7[7] = 72;
v7[8] = 51;
v7[9] = 110;
v7[10] = 103;
sub_4010F0(v7, 0, 10); // 对v7进行处理,处理后的数据
// 51 67 69 72 74 78 83 90 97 103 110
memset(v9, 0, 0xFFFFu); // 给v16清零
v9[0] = String[5];
v9[2] = String[7];
v9[1] = String[6];
v4 = sub_401000(v9, strlen(v9)); // 对v9进行base64加密然后传递给v4
memset(v9, 0, 0xFFFFu); // 给v9清零
v9[1] = String[3];
v9[0] = String[2];
v9[2] = String[4];
v5 = sub_401000(v9, strlen(v9)); // 对v9进行base64加密然后传递给v4
if ( String[0] == v7[0] + 34 // string[0] = 'U'
&& String[1] == v7[4] // string[1] = 'J'
&& 4 * String[2] - 141 == 3 * v7[2] // string[2] = 'W'
&& String[3] / 4 == 2 * (v7[7] / 9) // string[3] = 'P'
&& !strcmp(v4, "ak1w") // v4 = "ak1w"
&& !strcmp(
v5, // v5 = "V1Ax"
"V1Ax") )
{
MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0);
}
}
return 0;
}
if ( a3 != 1 && a3 != 2 )
return 0;
EndDialog(hDlg, a3);
return 1;
}
其中sub_4010F0(v7, 0, 10)函数,由于参数都是已知的,可以直接算出他处理的结果
// a1 为 v7对应地址
// a2 = 0
// a3 = 10
int __cdecl sub_4010F0(int *a1, int a2, int a3)
{
int result; // eax
int i; // esi
int v5; // ecx
int v6; // edx
result = a3; // result = 10
for ( i = a2; i <= a3; a2 = i ) // i=0;i<=10;a2=i
{
v5 = i;
v6 = a1[i]; // 遍历a1对应地址的元素
if ( a2 < result && i < result ) // a2<10 并且 i<10
{
do
{
if ( v6 > a1[result] ) // 如果a1[i] > a1[result]
{
if ( i >= result )
break; // 如果i>=result则退出循环
++i; // 给i+1
a1[v5] = a1[result]; // 让a1[1] = a1[result]
if ( i >= result )
break; // 如果i>=result则退出循环 重复
while ( a1[i] <= v6 ) // 当a1[i] <= v6 此循环一定成立
{
if ( ++i >= result ) // 如果i = result - 1
goto LABEL_13;
}
if ( i >= result )
break;
v5 = i;
a1[result] = a1[i];
}
--result; // result减一
}
while ( i < result );
}
LABEL_13:
a1[result] = v6; // 让a1[result] = 之前的a1[i]
sub_4010F0(a1, a2, i - 1); // 进行递归……
result = a3;
++i;
}
return result;
}
运行代码算出v7处理后各个元素的值……
sub_401000函数,,,
// a1 为 v9的地址
// a2 为 v9的长度
_BYTE *__cdecl sub_401000(int *a1, int a2)
{
int v2; // eax
int v3; // esi
size_t v4; // ebx
_BYTE *v5; // eax
_BYTE *v6; // edi
int v7; // eax
_BYTE *v8; // ebx
int v9; // edi
signed int v10; // edx
int v11; // edi
signed int v12; // eax
signed int v13; // esi
_BYTE *result; // eax
_BYTE *v15; // [esp+Ch] [ebp-10h]
_BYTE *v16; // [esp+10h] [ebp-Ch]
int v17; // [esp+14h] [ebp-8h]
int v18[4]; // [esp+18h] [ebp-4h]
v2 = a2 / 3;
v3 = 0;
if ( a2 % 3 > 0 )
++v2;
v4 = 4 * v2 + 1; // v4为长度
//
// 当进行编码的数据长度是3的倍数时,len=strlen(str_in)/3*4;
// 当进行编码的数据长度不是3的倍数时,len=(strlen(str_in)/3+1)*4;
// 为Base64加密
v5 = malloc(v4);
v6 = v5; // v6指向分配的动态内存空间
v15 = v5; // v15指向分配的动态内存空间
if ( !v5 )
exit(0); // 动态分配内存失败,退出
memset(v5, 0, v4); // 给分配的v5清零
v7 = a2;
v8 = v6; // v8指向分配的动态内存空间
v16 = v6; // v16指向分配的动态内存空间
if ( a2 > 0 )
{
while ( 1 )
{
v9 = 0;
v10 = 0;
v18[0] = 0;
do
{
if ( v3 >= v7 )
break;
++v10;
v9 = *(a1 + v3++) | (v9 << 8); // 将v9左移8位,然后与v9各个位二进制求或
}
while ( v10 < 3 );
v11 = v9 << 8 * (3 - v10); // v9向左移8的倍数位
v12 = 0;
v17 = v3;
v13 = 18;
do
{
if ( v10 >= v12 )
{
*(v18 + v12) = (v11 >> v13) & 63;
v8 = v16;
}
else
{
*(v18 + v12) = 64;
}
*v8++ = byte_407830[*(v18 + v12)]; // byte_407830 存放 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
// 此处更证明了为Base64加密
v13 -= 6;
++v12;
v16 = v8;
}
while ( v13 > -6 );
v3 = v17;
if ( v17 >= a2 )
break;
v7 = a2;
}
v6 = v15;
}
result = v6;
*v8 = 0;
return result;
}
v4 = “ak1w” v5 = “V1Ax” 使用在线网站https://c.runoob.com/front-end/693对v4和v5进行base64解密
string[5] = ‘j’
string[6] = ‘M’
string[7] = ‘p’
string[3] = ‘P’
string[2] = ‘W’
string[4] = ‘1’
可以得到string = “UJWP1jMp”
从而得到flag为 flag{UJWP1jMp}
往期回顾
小白学习笔记(0) CG-CTF-re-3 py交易
小白学习笔记(1) BUUCTF-re xor
小白学习笔记(2)BUUCTF-re-新年快乐
小白学习笔记(3) CG-CT re ReadAsm2
小白学习笔记(4)BUUCTF-re-reverse_1
小白学习笔记(5)BUUCTF-re-内涵软件
小白学习笔记(6)BUUCTF-re-SimpleRev
小白学习笔记(7)BUUCTF-re-rsa
小白学习笔记(8)BUUCTF-re-CrackRTF