re | [NPUCTF2020]Baby Obfuscation
[NPUCTF2020]Baby Obfuscation
好久不写博客了,哦准确的说是好久都没有学习了。
最近听没有耐心的,看题也没有大段大段的时间仔仔细细的看,今天算是静下心来好好的砍了一个题,虽然只有9分233333.
学习还是需要有耐心的,恩。
64位的windowsRE,所有东西基本都在主函数,没什么反调试。
主程序:
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // eax
int v4; // ebx
int v5; // esi
int v6; // ebx
int v7; // ebx
int v8; // esi
int v9; // edi
int v10; // ebx
int v11; // ebx
int v12; // ebx
int v13; // esi
int v14; // eax
int v15; // ebx
int v16; // esi
int v17; // ebx
int v18; // eax
bool v19; // bl
int v20; // eax
int v21; // esi
int v22; // ebx
int v23; // ebx
int v24; // eax
int v25; // eax
int v26; // eax
int v27; // eax
int v28; // ebx
int a[64]; // [rsp+20h] [rbp-60h]
int v31; // [rsp+120h] [rbp+A0h]
char input[1008]; // [rsp+130h] [rbp+B0h]
int convert[1000]; // [rsp+520h] [rbp+4A0h]
int v34; // [rsp+14C0h] [rbp+1440h]
int v35; // [rsp+14D0h] [rbp+1450h]
int v36; // [rsp+14D4h] [rbp+1454h]
int v37; // [rsp+14D8h] [rbp+1458h]
int v38; // [rsp+14DCh] [rbp+145Ch]
int v39; // [rsp+14E0h] [rbp+1460h]
int v40; // [rsp+14E4h] [rbp+1464h]
int v41; // [rsp+14E8h] [rbp+1468h]
int v42; // [rsp+14ECh] [rbp+146Ch]
int len; // [rsp+14F0h] [rbp+1470h]
int k; // [rsp+14F4h] [rbp+1474h]
int j; // [rsp+14F8h] [rbp+1478h]
int i; // [rsp+14FCh] [rbp+147Ch]
_main();
memset(convert, 0, sizeof(convert));
v34 = 0;
memset(a, 0, sizeof(a));
v31 = 0;
for ( i = 0; i <= 64; ++i ) // 初始化一个65位的数组从0到64
a[i] = i + 1;
v39 = 2; // 一些初始值 不知道干嘛的
//
v40 = 3;
v41 = 4;
v42 = 5;
v35 = 2;
v36 = 3;
v37 = 4;
v38 = 5;
puts("WHERE IS MY KEY!?");
scanf("%32s", input); // 输入字符串32位
len = strlen(input); // 获取长度
v3 = F0X1(a[j], a[j]); // 递归求最大公约数
//
// // FOX1 = gcd()
// // FOX5 = pow()
// // FOX4 = x-y
for ( j = v3 / a[j]; j <= len; ++j ) // 遍历数组a
{
v4 = (a[j] + a[j + 1]) * (a[j] + a[j + 1]);
if ( v4 >= F0X5(2, 2) * a[j] * a[j + 1] )
{
v5 = ~input[F0X4(j, 1)];
v6 = F0X4(j, 1);
convert[j] = ~(v5 + *(&v39 + v6 % F0X5(2, 2)));// F0X5( 2,2 )= 4
//
}
v7 = F0X1(a[j], a[j + 1]);
if ( v7 > F0X1(a[j + 1], ~(~a[j + 1] + a[j])) )
{
v8 = convert[j];
v9 = ~convert[j];
v10 = F0X4(j, 1);
convert[j] = ~(v9 + a[v10 % F0X5(2, 2)]) * v8;
}
v11 = a[j + 1];
v12 = F0X5(2, 1) * v11;
v13 = a[j];
v14 = F0X5(2, 1);
v15 = F0X1(v13 * v14, v12);
v16 = F0X5(2, 1);
if ( v15 == v16 * F0X1(a[j], a[j + 1]) )
{
v17 = F0X4(j, 1);
convert[j] ^= *(&v39 + v17 % F0X5(2, 2));
}
v18 = F0X5(V0X3, a[j]);
v19 = v18 < a[j] + 1;
v20 = F0X5(2, 4);
if ( F0X3(v20 >= j, v19) )
{
v21 = ~input[F0X4(j, 1)];
v22 = F0X4(j, 1);
convert[j] ^= ~(v21 + *(&v39 + v22 % F0X5(2, 2)));
}
v23 = F0X5(2, 3);
v24 = F0X1(a[j], a[j]);
convert[j] *= v23 + F0X5(2, v24 / a[j]);
}
v25 = F0X5(2, 4); // 16
v26 = F0X4(v25, 1); // 15
if ( v26 == len ) // 输入长度为15
{
v27 = F0X1(a[k], a[k]);
for ( k = v27 / a[k]; k <= len; ++k )
{
v28 = convert[k];
if ( v28 == F0X4(A0X6[k], 1) / 10 ) // 这里是最后的判断
++V0X2;
}
if ( V0X2 == len )
puts("\nPASS");
else
puts("\nDENIED");
}
else
{
puts("\nDENIED");
}
return 0;
}
分析一下不难发现每一位相对应的是有对应的值,当然其中的那些函数只不过是把程序复杂化的一种手段,很容易能看出来是啥作用,实在不行就动态调试一下就好了。
然后就是对于转化函数的爆破,这里本来想手动的,但是好像太多了,还是写了一下脚本,直接把程序贴出来改就好了。
exp:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int __cdecl F0X1(int a, int b)
{
int result; // eax
if ( b )
result = F0X1(b, a % b);
else
result = a;
return result;
}
int __cdecl F0X4(int a, int b)
{
return ~(~a + b);
}
int __cdecl F0X5(int a, int b)
{
int base; // [rsp+8h] [rbp-8h]
signed int ans; // [rsp+Ch] [rbp-4h]
int ba; // [rsp+28h] [rbp+18h]
ba = b;
ans = 1;
base = a;
while ( ba )
{
if ( ba & 1 )
ans *= base;
base *= base;
ba >>= 1;
}
return ans;
}
bool __cdecl F0X2(bool a, bool b)
{
return a == b && a != 1;
}
bool __cdecl F0X3(bool a, bool b)
{
bool v2; // bl
bool v3; // al
bool aa; // [rsp+40h] [rbp-40h]
aa = a;
v2 = F0X2(b, b);
v3 = F0X2(aa, aa);
return F0X2(v3, v2);
}
int V0X2 = 0;
int V0X3 = 3;
int A0X6[17] = {0, 0x1E79, 0x1E79, 0x2135,
0x170D, 0x1F41, 0x1901, 0x2CED,
0x11F9, 0x2649, 0x2581, 0x2DB5,
0x14B5, 0x25E5, 0x2A31, 0x30D5,
0};
int aim[15] = {0x30c,0x30c,0x352,0x24e,0x320,0x280,0x47e,0x1cc,0x3d4,0x3c0,0x492,0x212,0x3ca,0x438,0x4e2};
int main(int argc, const char **argv, const char **envp)
{
int v3; // eax
int v4; // ebx
int v5; // esi
int v6; // ebx
int v7; // ebx
int v8; // esi
int v9; // edi
int v10; // ebx
int v11; // ebx
int v12; // ebx
int v13; // esi
int v14; // eax
int v15; // ebx
int v16; // esi
int v17; // ebx
int v18; // eax
bool v19; // bl
int v20; // eax
int v21; // esi
int v22; // ebx
int v23; // ebx
int v24; // eax
int v25; // eax
int v26; // eax
int v27; // eax
int v28; // ebx
int a[65]; // [rsp+20h] [rbp-60h]
char input[1008]; // [rsp+130h] [rbp+B0h]
int convert[1000]; // [rsp+520h] [rbp+4A0h]
int v34; // [rsp+14C0h] [rbp+1440h]
int v35; // [rsp+14D0h] [rbp+1450h]
int v36; // [rsp+14D4h] [rbp+1454h]
int v37; // [rsp+14D8h] [rbp+1458h]
int v38; // [rsp+14DCh] [rbp+145Ch]
int v39; // [rsp+14E0h] [rbp+1460h]
int v40; // [rsp+14E4h] [rbp+1464h]
int v41; // [rsp+14E8h] [rbp+1468h]
int v42; // [rsp+14ECh] [rbp+146Ch]
int len; // [rsp+14F0h] [rbp+1470h]
int k; // [rsp+14F4h] [rbp+1474h]
int j = 0; // [rsp+14F8h] [rbp+1478h]
int i; // [rsp+14FCh] [rbp+147Ch]
int vv39[4] = {2,3,4,5};
memset(convert, 0, sizeof(convert));
memset(a, 0, sizeof(a));
for ( i = 0; i <= 64; ++i ) // 初始化一个65位的数组从0到64
a[i] = i + 1;
v34 = 0;
v35 = 2;
v36 = 3;
v37 = 4;
v38 = 5;
v39 = 2; // 一些初始值 不知道干嘛的
v40 = 3;
v41 = 4;
v42 = 5;
j= 1; // 这里要加初始值不然跑不起来
puts("WHERE IS MY KEY!?");
scanf("%32s", input); // 输入字符串32位
len = strlen(input); // 获取长度 长度应该为15
v3 = F0X1(a[j], a[j]); // 递归求最大公约数
//
// // FOX1 = gcd()
// // FOX5 = pow()
// // FOX4 = x-y
for ( j = v3 / a[j]; j <= len; ++j ) // 遍历数组a
{
for (char mmz = 33; mmz < 127; mmz ++){ // 开始爆破!!!!!
v4 = (a[j] + a[j + 1]) * (a[j] + a[j + 1]);
if ( v4 >= F0X5(2, 2) * a[j] * a[j + 1] )
{
v5 = ~mmz; // 这里是输入点
v6 = F0X4(j, 1);
convert[j] = ~(v5 + *(vv39 + v6 % F0X5(2, 2)));// F0X5( 2,2 )= 4
//
}
v7 = F0X1(a[j], a[j + 1]);
if ( v7 > F0X1(a[j + 1], ~(~a[j + 1] + a[j])) )
{
v8 = convert[j];
v9 = ~convert[j];
v10 = F0X4(j, 1);
convert[j] = ~(v9 + a[v10 % F0X5(2, 2)]) * v8;
}
v11 = a[j + 1];
v12 = F0X5(2, 1) * v11;
v13 = a[j];
v14 = F0X5(2, 1);
v15 = F0X1(v13 * v14, v12);
v16 = F0X5(2, 1);
if ( v15 == v16 * F0X1(a[j], a[j + 1]) )
{
v17 = F0X4(j, 1);
convert[j] ^= *(vv39 + v17 % F0X5(2, 2));
}
v18 = F0X5(V0X3, a[j]);
v19 = v18 < a[j] + 1;
v20 = F0X5(2, 4);
if ( F0X3(v20 >= j, v19) )
{
v21 = ~mmz;
v22 = F0X4(j, 1);
convert[j] ^= ~(v21 + *(vv39 + v22 % F0X5(2, 2)));
}
v23 = F0X5(2, 3);
v24 = F0X1(a[j], a[j]);
convert[j] *= v23 + F0X5(2, v24 / a[j]);
// 爆破条件判断
if (convert[j] == aim[j-1]){
printf("%c", mmz);
break;
}
}
/*
v4 = (a[j] + a[j + 1]) * (a[j] + a[j + 1]);
if ( v4 >= F0X5(2, 2) * a[j] * a[j + 1] )
{
v5 = ~input[F0X4(j, 1)];
v6 = F0X4(j, 1);
convert[j] = ~(v5 + *(vv39 + v6 % F0X5(2, 2)));// F0X5( 2,2 )= 4
//
}
v7 = F0X1(a[j], a[j + 1]);
if ( v7 > F0X1(a[j + 1], ~(~a[j + 1] + a[j])) )
{
v8 = convert[j];
v9 = ~convert[j];
v10 = F0X4(j, 1);
convert[j] = ~(v9 + a[v10 % F0X5(2, 2)]) * v8;
}
v11 = a[j + 1];
v12 = F0X5(2, 1) * v11;
v13 = a[j];
v14 = F0X5(2, 1);
v15 = F0X1(v13 * v14, v12);
v16 = F0X5(2, 1);
if ( v15 == v16 * F0X1(a[j], a[j + 1]) )
{
v17 = F0X4(j, 1);
convert[j] ^= *(vv39 + v17 % F0X5(2, 2));
}
v18 = F0X5(V0X3, a[j]);
v19 = v18 < a[j] + 1;
v20 = F0X5(2, 4);
if ( F0X3(v20 >= j, v19) )
{
v21 = ~input[F0X4(j, 1)];
v22 = F0X4(j, 1);
convert[j] ^= ~(v21 + *(vv39 + v22 % F0X5(2, 2)));
}
v23 = F0X5(2, 3);
v24 = F0X1(a[j], a[j]);
convert[j] *= v23 + F0X5(2, v24 / a[j]);*/
}
// 输出convert的结果来对比
for (int mz = 1; mz <= len; mz ++){
printf("%x \n", convert[mz]);
}
v25 = F0X5(2, 4); // 16
v26 = F0X4(v25, 1); // 15
if ( v26 == len ) // 输入长度为15
{
v27 = F0X1(a[k], a[k]);
for ( k = v27 / a[k]; k <= len; ++k )
{
v28 = convert[k];
if ( v28 == F0X4(A0X6[k], 1) / 10 ) // 这里是最后的判断
++V0X2;
}
if ( V0X2 == len )
puts("\nPASS");
else
puts("\nDENIED");
}
else
{
puts("\nDENIED");
}
return 0;
}
结果如下:
本文来自博客园,作者:Mz1,转载请注明原文链接:https://www.cnblogs.com/Mz1-rc/p/15724743.html
如果有问题可以在下方评论或者email:mzi_mzi@163.com