这题有一堆整不明白的加密函数,每次输入一个数,加密处理后如果正确就放到串里,最后这个串的md5给出了,然后再用sha1的加密后数据进行一个简单加密得到flag
没办法只能gdb一点点跟进。
__int64 __fastcall main(int a1, char **a2, char **a3)
{
size_t v3; // rax
size_t v4; // rax
const char *v5; // rsi
char v7[48]; // [rsp+90h] [rbp-210h]
char s1[48]; // [rsp+C0h] [rbp-1E0h]
char v9[32]; // [rsp+F0h] [rbp-1B0h]
char v10[28]; // [rsp+110h] [rbp-190h]
int i; // [rsp+12Ch] [rbp-174h]
char v12; // [rsp+130h] [rbp-170h]
char v13; // [rsp+190h] [rbp-110h]
char s; // [rsp+1F0h] [rbp-B0h]
int v15; // [rsp+27Ch] [rbp-24h]
unsigned int v16; // [rsp+280h] [rbp-20h]
unsigned int v17; // [rsp+284h] [rbp-1Ch]
int v18; // [rsp+288h] [rbp-18h]
unsigned int v19; // [rsp+28Ch] [rbp-14h]
char **v20; // [rsp+290h] [rbp-10h]
int v21; // [rsp+298h] [rbp-8h]
unsigned int v22; // [rsp+29Ch] [rbp-4h]
v22 = 0;
v21 = a1;
v20 = a2;
printf("I will generate some random numbers.\n", a2, a3);
printf("If you can give me those numbers, you will be $$rewarded$$\n");
printf("hmm..thinking...");
fflush(stdout);
rand();
v19 = rand();
v18 = 0;
printf("OK. I am Ready. Enter Numbers.\n");
v15 = sub_400C30(v19);
v16 = (1 << sub_400B40(v19)) - 1;
MD5_Init(&v13);
SHA1_Init(&v12);
while ( v18 != v19 )
{
__isoc99_scanf("%d", &v17);
if ( !(unsigned int)sub_400EA0(v16, v17) )
sub_400AE0();
v16 += v17;
sprintf(&s, "%d", v17);
v3 = strlen(&s);
MD5_Update(&v13, &s, v3);
v4 = strlen(&s);
SHA1_Update(&v12, &s, v4);
while ( (~v15 | ~v16) != -1 )
{
v18 = v15 ^ v18 | v15 & v18;
v16 &= v15 ^ v16;
v15 = sub_400C30(v19 & (v18 ^ v19));
}
}
MD5_Final(v10, &v13);
for ( i = 0; i < 16; ++i )
sprintf(&s1[2 * i], "%02x", (unsigned __int8)v10[i]);
if ( strcmp(s1, (const char *)(unsigned int)"15b74b4db57d0afdfe98eb5dbc3b542b") )
sub_400AE0();
printf("Good Job!!\n");
printf("Wait till I fetch your reward...");
fflush(stdout);
v5 = &v12;
rand();
SHA1_Final(v9, &v12);
for ( i = 0; i < 20; ++i )
{
v5 = "%02x";
sprintf(&v7[2 * i], "%02x", (unsigned __int8)v9[i]);
}
printf("OK. Here it is\n", v5);
for ( i = 0; i < 40; ++i )
v7[i] = (dword_6020D0[i] & 0x4A | ~LOBYTE(dword_6020D0[i]) & 0xB5) ^ (v7[i] & 0x4A | ~v7[i] & 0xB5);
printf("The flag is:nullcon{%s}\n", v7);
return v22;
}
先随便输入个数,然后断在0x401004,正确的值应该是$rdi-*(int *)($rbp-0xc)不过这样每次只能跟到一个数,不过可以猜,第1行头是0x8000然后是*=2,到一定值后为上一个头的一半0x4000。弄到30多个失去耐心了,看了下网上的exp,用的angr。不过这东西一直也装不上。最后一共有120多项。
不过这里在中间会报错,如果不报错的话,一次测一行,用gdb脚本,到不正确的时候停掉,每次一行应该也能完成。
from pwn import *
from hashlib import md5,sha1
dword_6020D0 = [0x0D,0x52,0x67,0x53,0x44,0x40,0x16, 0x8,
0x51,0x67, 0x6,0x0B,0x52, 0x3, 0x0, 0x0,
0x5F, 0x1,0x0B,0x6F,0x53,0x55,0x43,0x6A,
0x53,0x50,0x5B, 0x5,0x51, 0x4,0x10,0x3A,
0x1, 0x54,0x5C, 0x7,0x4E,0x41,0x9, 0x46]
v18 = [0x8000, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000, 0x200000, 0x400000, 0x800000, 0x1000000, 0x2000000, 0x4000000, 0x8000000, 0x10000000, #14
0x4000, 0x8000, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000, 0x200000, 0x400000, 0x800000, 0x1000000, 0x2000000, 0x4000000, 0x8000000, #14
0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000, 0x200000, 0x400000, 0x800000, 0x1000000, #12
0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000, 0x200000, #10
0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000,
0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000, 0x80000,
0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000,
0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, #9
0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, #9
0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, #7
0x20, 0x40, 0x80, 0x100, #4
0x10, 0x20, 0x40, 0x80,
0x8, 0x10, 0x20, 0x40,
0x4, 0x8, 0x10, 0x20,
2, #1
1]
p = process('./pseudorandom')
p.recv()
context(log_level='debug')
a = ''
for i in v18:
print(i, hex(i))
#p.sendline(str(i).encode())
a +=str(i)
#p.recv()
print(md5(a.encode()).hexdigest())
print(sha1(a.encode()).hexdigest())
'''
for ( i = 0; i < 40; ++i )
v8[i] = (dword_6020D0[i] & 0x4A | ~LOBYTE(dword_6020D0[i]) & 0xB5) ^ (v8[i] & 0x4A | ~v8[i] & 0xB5);
'''
v8 = sha1(a.encode()).hexdigest()
v8 = [ord(i) for i in v8]
for i in range(40):
v8[i] = (dword_6020D0[i] & 0x4A | ~dword_6020D0[i] & 0xB5) ^ (v8[i] & 0x4A | ~v8[i] & 0xB5)
print(b'nullcon{' + bytes(v8) + b'}')
pause()
输入正确后会显示flag,后边是改成不用运行程序直接写结果的。