Binary Overflow.

湖湘杯Replace题解

字数统计: 1.7k阅读时长: 9 min
2018/11/18 Share

0x00 前言


题目来自湖湘杯 Reverse Replace 题目不算太难但是逻辑很复杂

0x01 关键点寻找


先把文件脱壳 带入IDA中看


里面有个重点输入buf必须是35长度
进入sub_401090函数看看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
signed int __fastcall sub_401090(int a1, int a2)
{
int v2; // ebx
int v4; // edx
char v5; // al
int v6; // esi
int v7; // edi
char v8; // al
int v9; // eax
char v10; // cl
int v11; // eax
int v12; // ecx

v2 = a1;
if ( a2 != 35 )
return -1;
v4 = 0;
while ( 1 )
{
v5 = *(_BYTE *)(v4 + v2);
v6 = (v5 >> 4) % 16;
v7 = (16 * v5 >> 4) % 16;
v8 = unk_402150[2 * v4];
if ( v8 < 48 || v8 > 57 )
v9 = v8 - 87;
else
v9 = v8 - 48;
v10 = byte_402151[2 * v4];
v11 = 16 * v9;
if ( v10 < 48 || v10 > 57 )
v12 = v10 - 87;
else
v12 = v10 - 48;
if ( (unsigned __int8)byte_4021A0[16 * v6 + v7] != ((v11 + v12) ^ 0x19) )
break;
if ( ++v4 >= 35 )
return 1;
}
return -1;
}

需要这个函数返回1 那肯定是要完成

1
2
if ( ++v4 >= 35 )
return 1;

那看看上面的函数逻辑 v5 = *(_BYTE *)(v4 + v2);v2被a1赋值a1就是我们输入的buf v4从0开始每次循环+1
接着看一下下面v6 = (v5 >> 4) % 16; v6=(输入的每个字符/16)%16
v7 = (16 * v5 >> 4) % 16; v7= v5%16
v8 = unk_402150[2 * v4]; v8为一个数组中2v4的变量 我们暂且叫这个数组为arr1 v8=arr1[2v4]

1
2
3
4
if ( v8 < 48 || v8 > 57 )
v9 = v8 - 87;
else
v9 = v8 - 48;

这一段是判断v8去对v9进行操作
v10 = byte_402151[2 * v4];v10等于另外一个数组的2v4个元素 我们暂且叫这个数组为arr2 v10 = arr2[2v4]

1
2
3
4
if ( v10 < 48 || v10 > 57 )
v12 = v10 - 87;
else
v12 = v10 - 48;

下面就是一个重点 这是整个代码的关键所在 在byte_4021A0这个数组中的16v6+v7的位置上的字符 需要和v11+v12对0x19的异或值相等才可以
简洁而写就是byte_4021A0[16
v6+v7] == (v11+v12)^0x19

0x02 GETflag


整理了所有逻辑后我们就去思维逆回去 我们需要有一个字符串 长度必须是35 而且字符串中每一个都在if ( (unsigned __int8)byte_4021A0[16 * v6 + v7] != ((v11 + v12) ^ 0x19) )
可以跳过 那可以想象得到 估计这个就是flag字符串了 那我们怎么得到这个字符串呢 最简单方法 爆破 从所有可见字符一个一个试试 看到哪一个成立就行 先看一下byte_4021A0byte_402151byte_402150
数组中存的都是什么

可以看的出来byte_402151byte_402150是连着的 byte_402150存的是2a49f69c38395cde96d6de96d6f4e025484954d6195448def6e2dad67786e21d5adae6
而byte_402151存的是 a49f69c38395cde96d6de96d6f4e025484954d6195448def6e2dad67786e21d5adae6

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
.rdata:004021A0 byte_4021A0     db 63h, 7Ch, 77h, 7Bh, 0F2h, 6Bh, 6Fh, 0C5h, 30h, 1, 67h
.rdata:004021A0 ; DATA XREF: sub_401090+82↑r
.rdata:004021A0 db 2Bh, 0FEh, 0D7h, 0ABh, 76h, 0CAh, 82h, 0C9h, 7Dh, 0FAh
.rdata:004021A0 db 59h, 47h, 0F0h, 0ADh, 0D4h, 0A2h, 0AFh, 9Ch, 0A4h, 72h
.rdata:004021A0 db 0C0h, 0B7h, 0FDh, 93h, 26h, 36h, 3Fh, 0F7h, 0CCh, 34h
.rdata:004021A0 db 0A5h, 0E5h, 0F1h, 71h, 0D8h, 31h, 15h, 4, 0C7h, 23h
.rdata:004021A0 db 0C3h, 18h, 96h, 5, 9Ah, 7, 12h, 80h, 0E2h, 0EBh, 27h
.rdata:004021A0 db 0B2h, 75h, 9, 83h, 2Ch, 1Ah, 1Bh, 6Eh, 5Ah, 0A0h, 52h
.rdata:004021A0 db 3Bh, 0D6h, 0B3h, 29h, 0E3h, 2Fh, 84h, 53h, 0D1h, 0
.rdata:004021A0 db 0EDh, 20h, 0FCh, 0B1h, 5Bh, 6Ah, 0CBh, 0BEh, 39h, 4Ah
.rdata:004021A0 db 4Ch, 58h, 0CFh, 0D0h, 0EFh, 0AAh, 0FBh, 43h, 4Dh, 33h
.rdata:004021A0 db 85h, 45h, 0F9h, 2, 7Fh, 50h, 3Ch, 9Fh, 0A8h, 51h, 0A3h
.rdata:004021A0 db 40h, 8Fh, 92h, 9Dh, 38h, 0F5h, 0BCh, 0B6h, 0DAh, 21h
.rdata:004021A0 db 10h, 0FFh, 0F3h, 0D2h, 0CDh, 0Ch, 13h, 0ECh, 5Fh, 97h
.rdata:004021A0 db 44h, 17h, 0C4h, 0A7h, 7Eh, 3Dh, 64h, 5Dh, 19h, 73h
.rdata:004021A0 db 60h, 81h, 4Fh, 0DCh, 22h, 2Ah, 90h, 88h, 46h, 0EEh
.rdata:004021A0 db 0B8h, 14h, 0DEh, 5Eh, 0Bh, 0DBh, 0E0h, 32h, 3Ah, 0Ah
.rdata:004021A0 db 49h, 6, 24h, 5Ch, 0C2h, 0D3h, 0ACh, 62h, 91h, 95h, 0E4h
.rdata:004021A0 db 79h, 0E7h, 0C8h, 37h, 6Dh, 8Dh, 0D5h, 4Eh, 0A9h, 6Ch
.rdata:004021A0 db 56h, 0F4h, 0EAh, 65h, 7Ah, 0AEh, 8, 0BAh, 78h, 25h
.rdata:004021A0 db 2Eh, 1Ch, 0A6h, 0B4h, 0C6h, 0E8h, 0DDh, 74h, 1Fh, 4Bh
.rdata:004021A0 db 0BDh, 8Bh, 8Ah, 70h, 3Eh, 0B5h, 66h, 48h, 3, 0F6h, 0Eh
.rdata:004021A0 db 61h, 35h, 57h, 0B9h, 86h, 0C1h, 1Dh, 9Eh, 0E1h, 0F8h
.rdata:004021A0 db 98h, 11h, 69h, 0D9h, 8Eh, 94h, 9Bh, 1Eh, 87h, 0E9h
.rdata:004021A0 db 0CEh, 55h, 28h, 0DFh, 8Ch, 0A1h, 89h, 0Dh, 0BFh, 0E6h
.rdata:004021A0 db 42h, 68h, 41h, 99h, 2Dh, 0Fh, 0B0h, 54h, 0BBh, 16h

这是byte_4021A0里面存的东西 这是我把它变成arrary形式的变量值 但会发现从ida中不好提取出来 问了丁佬才知道ida有一个插件lazyida的方法可以去提取data
右键byte_4021A0有一个Convent 选择后Convent to python list[Byte]

1
2
[+] Dump 0x4021A0 - 0x4022A0 (256 bytes) :
[0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16]

下面就是脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/usr/bin/python
arr=[0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16]
str1 = "2a49f69c38395cde96d6de96d6f4e025484954d6195448def6e2dad67786e21d5adae6"
str2 = "a49f69c38395cde96d6de96d6f4e025484954d6195448def6e2dad67786e21d5adae6"
flag =''
def change(index):
if index <48 or index >57:
index = index - 87
else:
index = index - 48
return index
while True:
for i in range(0,35):
for char in range(33,126):
t1 = arr[char%16+((char/16)%16)*16]
t2 = (change(ord(str1[2*i]))*16 + change(ord(str2[2*i])))^0x19
if t1 == t2 :
flag += chr(char)
print flag
if flag[-1] == '}' :
exit(0)

最后得到flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
f
fl
fla
flag
flag{
flag{T
flag{Th
flag{Th1
flag{Th1s
flag{Th1s_
flag{Th1s_1
flag{Th1s_1s
flag{Th1s_1s_
flag{Th1s_1s_S
flag{Th1s_1s_Si
flag{Th1s_1s_Sim
flag{Th1s_1s_Simp
flag{Th1s_1s_Simpl
flag{Th1s_1s_Simple
flag{Th1s_1s_Simple_
flag{Th1s_1s_Simple_R
flag{Th1s_1s_Simple_Re
flag{Th1s_1s_Simple_Rep
flag{Th1s_1s_Simple_Rep1
flag{Th1s_1s_Simple_Rep1a
flag{Th1s_1s_Simple_Rep1ac
flag{Th1s_1s_Simple_Rep1ac3
flag{Th1s_1s_Simple_Rep1ac3_
flag{Th1s_1s_Simple_Rep1ac3_E
flag{Th1s_1s_Simple_Rep1ac3_En
flag{Th1s_1s_Simple_Rep1ac3_Enc
flag{Th1s_1s_Simple_Rep1ac3_Enc0
flag{Th1s_1s_Simple_Rep1ac3_Enc0d
flag{Th1s_1s_Simple_Rep1ac3_Enc0d3
flag{Th1s_1s_Simple_Rep1ac3_Enc0d3}

CATALOG
  1. 1. 0x00 前言
  2. 2. 0x01 关键点寻找
  3. 3. 0x02 GETflag