gunnew의 잡설

pwnable.kr 4. flag (UPX unpacking problem) 본문

System Security

pwnable.kr 4. flag (UPX unpacking problem)

higunnew 2020. 2. 2. 23:59
반응형

이번 문제는 뭘까... 두려움이 앞선다. 

 

 

Reverse engineering 인듯 하다. 어떻게 하는 건지는 잘 모르겠지만 우선 다음 명령어를 통해 파일을 다운받자.

 

wget http://pwnable.kr/bin/flag

 


 그리고 flag를 실행해보았더니 malloc을 했고, 거기에 flag를 strcpy 해 놓았단다. 그러면 이것도 뭐 gdb 겠거니 하면서 gdb를 켜보자.


 

1. gdb로 열어보기

 

 

 

띠용??

띠용?? file을 열 수 없다고? 왜지? 흠... 그러면 한번 binary file을 열어보자.


2. UPX 다운로드 및 Unpacking

 

vi flag (binary file을 vi로 읽음)

 

 자 이제 기계어로 된 binary file인 flag를 vi로 읽어보자. 그랬더니 위의 괴상한 문자들이 나오는데 그 와중에 UPX라는 글자가 보인다. UPX를 찾아보았더니 UPX는 아무튼 알집하고 비슷한 압축 툴인것 같다. 그럼 UPX를 다운받자.

 

 근데 왜인지는 모르겠으나 다음과 같은 명령어를 통해 upx를 깔고 실행해 봤는데 안된다. 

kimk@ubuntu:~/Desktop/security/flag$ sudo snap install upx
[sudo] password for kimk: 
upx v0.2.3 from HanYec (hyc320) installed
kimk@ubuntu:~/Desktop/security/flag$ upx -d ./flag
Incorrect Usage.

 

그래서 한참을 찾다가 그냥 firefox로 들어가서 다운받아서 실행파일만 flag가 있는 폴더로 옮겨 버렸다. 이 사이트로 들어가서 최근 것 다운 받아서 압축풀고 밑에 사진대로 따라가면 된다.

https://github.com/upx/upx/releases

 

upx/upx

UPX - the Ultimate Packer for eXecutables. Contribute to upx/upx development by creating an account on GitHub.

github.com

 

 

이거 복사해서!
flag 파일이 있는 곳으로 실행 파일만 쏙 옮기자!


3. Unpacking 및 gdb 실행, disassembly code 분석

  

 자! 이제 upx 실행파일도 가져왔겠다. unpacking을 해보자. 

 

./upx -d flag를 하면 압축이 풀린다.

 

이제 gdb를 통해 disassembly code를 까보자.

 

disassembly code

 

 위 코드를 가만히 보자니 일단 malloc을 통해 0x64 (100)bytes만큼 할당한 것까지는 눈에 띈다. 그 다음을 보면    0x0000000000401184 <+32>: mov    rdx, QWORD PTR [rip+0x2c0ee5] 이 부분을 볼 수 있는데 rip는 64bit에서 다음 실행할 부분의 주소를 나타낸다. 그런데 rdx에다가 우리가 보고자 하는 <flag>가 있는 곳에 있는 값을 넘겨주었다. 아마 이 부분에는 문자열이 시작되므로 문자열의 주소가 저장되어 있을 것이다.

 

 그리고 

   0x000000000040118b <+39>: mov    rax, QWORD PTR [rbp-0x8

이 부분을 통해서 rbp-0x8 즉, main 함수 내 스택에 있는 지역 변수에 있는 주소를 rax로 옮기고 이것을 

 

   0x0000000000401192 <+46>: mov    rdi,rax 

를 통해 rdi로 옮긴다. 

 

또한 

   0x000000000040118f <+43>: mov    rsi,rdx 

이 부분을 통해서 그 문자열의 주소를 rsi로 옮겨 놓은 후에

 

   0x0000000000401195 <+49>: call   0x400320 

로 시스템 콜을 하는 것으로 보인다.

 

 


Dump of assembler code for function main:
   0x0000000000401164 <+0>: push   rbp
   0x0000000000401165 <+1>: mov    rbp,rsp
   0x0000000000401168 <+4>: sub    rsp,0x10
   0x000000000040116c <+8>: mov    edi,0x496658
   0x0000000000401171 <+13>: call   0x402080 
   0x0000000000401176 <+18>: mov    edi,0x64
   0x000000000040117b <+23>: call   0x4099d0 
   0x0000000000401180 <+28>: mov    QWORD PTR [rbp-0x8],rax
   0x0000000000401184 <+32>: mov    rdx, QWORD PTR [rip+0x2c0ee5]   # 0x6c2070  <flag>
   0x000000000040118b <+39>: mov    rax, QWORD PTR [rbp-0x8]
   0x000000000040118f <+43>: mov    rsi,rdx
   0x0000000000401192 <+46>: mov    rdi,rax
   0x0000000000401195 <+49>: call   0x400320
   0x000000000040119a <+54>: mov    eax,0x0
   0x000000000040119f <+59>: leave  
   0x00000000004011a0 <+60>: ret    
End of assembler dump.


 자 그럼 우리가 유심히 봐야할 곳은 시스템 콜 call 0x400320이 되기 직전과 그 이후이다. 그러면 breakpoint를 해당 주소 (0x401195)에 다음과 같이 걸어준다. 

 

(gdb) b *0x401195
Breakpoint 1 at 0x401195
(gdb) run
Starting program: /home/kimk/Desktop/security/flag/flag 
I will malloc() and strcpy the flag there. take it.

Breakpoint 1, 0x0000000000401195 in main ()

 

이제 중단점에서 info reg를 통해 reg에 있는 값들을 살펴보자. 우리가 유심히 봐야하는 레지스터는 최종적으로 rsi와 rdi와 옮긴 것을 디스어셈블리 코드에서 확인했으니까 rsi와 rdi만 보면 된다. 사실 가만 생각해보면 rsi는 source index를, rdi는 destination index를 나타내는 레지스터이기 때문에 시스템 콜을 하기 전에 해당 레지스터에는 목표로 하는 작업을 위해 정확한 값이 들어가야 한다. 그러니까 시스템 콜을 하면 당연히 rsi에는 source가, rdi는 destination이 있을 거라 생각하기 때문에 우리는 source가 되는 부분에 있는 문자열을 보거나, 혹은 시스템 콜이 완료되고 rdi에 있는 문자열을 보면 된다.

 

 먼저 rdi에 문자열로 뭐가 있는지 보기 위해 

(gdb) x/s 0x6c96b0

을 입력했으나 밑에 사진과 같이 ""이 나온다. 아직 안 옮겨졌으니까 당연하다.

 

info reg

 

 그럼 이제 next 실행하고 rdi를 다시 확인해보자.

 

시스템 콜 이후 rdi에 있는 문자열

 짜잔! 정답이 나왔다. UPX...? ~~~ 이것이 우리가 목표로 하는 flag이다.

 

아 물론 rsi에 있는 값을 진작에 확인했어도 됐다. rsi에 0x496628이 있었으니까 거기에 있는 것을 문자열로 표현해봤더니 rdi랑 똑같다. (당연하지 strcpy인데)

rsi에 있는 문자열

 

 

 

반응형

'System Security' 카테고리의 다른 글

pwnable.kr 6. random  (0) 2020.02.05
pwnable.kr 5. passcode  (0) 2020.02.04
pwnable.kr 3. bof (Buffer overflow) (Stack smashing)  (0) 2020.02.02
pwnable.kr 2. collision  (0) 2020.02.02
pwnable.kr 1. fd(File Descriptor)  (0) 2020.02.02
Comments