Two Pwns a Week Challenge(3) - flag
# flag
**先備知識**
- basic assembly
**知識點**
- basic use of gdb
- objdump
- packer
```
Papa brought me a packed present! let's open it.
Download : http://pwnable.kr/bin/flag
This is reversing task. all you need is binary
```
下載下來之後,先跑一下看看
```shell
$ ./flag
I will malloc() and strcpy the flag there. take it.
```
什麼輸入都沒有,就印這行字
代表我們可能要直接進去找flag
`checksec`一下看看程式開了哪些保護
```shell
$ checksec flag
[*] '/flag'
Arch: amd64-64-little
RELRO: No RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x400000)
RWX: Has RWX segments
Packer: Packed with UPX
```
注意到最後面寫了個`Packer: Packed with UPX`
這個packer的中文叫做「殼」
這個運作原理我也搞不懂
總而言之,「殼」就是一層包在原本程式外面的東東
有些殼能減少程式的大小,有些能讓程式反編譯後解讀困難等等的
所以他這個`Packer: Packed with UPX`
意思就是外面有個UPX殼就對了
啊既然有殼,我們就解
UPX的網址放在這裡 [https://upx.github.io](https://upx.github.io)
想辦法搞到upx之後
```shell
$ upx -d flag
Ultimate Packer for eXecutables
Copyright (C) 1996 - 2017
UPX 3.94 Markus Oberhumer, Laszlo Molnar & John Reiser May 12th 2017
File size Ratio Format Name
-------------------- ------ ----------- -----------
883745 <- 335288 37.94% linux/amd64 flag
Unpacked 1 file.
```
現在殼拿掉了,我們可以用`objdump`這個指令來看看assembly
`-M`指定語法(assembly大致上有兩種語法:intel跟AT&T,我習慣看intel)
`-d`指定要看哪個檔案
```shell
$ objdump -M intel -d flag
flag: file format elf64-x86-64
Disassembly of section .init:
00000000004002f8 <_init>:
4002f8: 48 83 ec 08 sub rsp,0x8
4002fc: e8 83 0d 00 00 call 401084 <call_gmon_start>
400301: e8 1a 0e 00 00 call 401120 <frame_dummy>
400306: e8 f5 49 09 00 call 494d00 <__do_global_ctors_aux>
40030b: 48 83 c4 08 add rsp,0x8
40030f: c3 ret
Disassembly of section .plt:
0000000000400310 <.plt>:
400310: ff 25 ea 1c 2c 00 jmp QWORD PTR [rip+0x2c1cea] # 6c2000 <_GLOBAL_OFFSET_TABLE_+0x18>
400316: 68 00 00 00 00 push 0x0
40031b: e9 00 00 00 00 jmp 400320 <.plt+0x10>
400320: ff 25 e2 1c 2c 00 jmp QWORD PTR [rip+0x2c1ce2] # 6c2008 <_GLOBAL_OFFSET_TABLE_+0x20>
400326: 68 00 00 00 00 push 0x0
40032b: e9 00 00 00 00 jmp 400330 <.plt+0x20>
400330: ff 25 da 1c 2c 00 jmp QWORD PTR [rip+0x2c1cda] # 6c2010 <_GLOBAL_OFFSET_TABLE_+0x28>
400336: 68 00 00 00 00 push 0x0
40033b: e9 00 00 00 00 jmp 400340 <.plt+0x30>
400340: ff 25 d2 1c 2c 00 jmp QWORD PTR [rip+0x2c1cd2] # 6c2018 <_GLOBAL_OFFSET_TABLE_+0x30>
400346: 68 00 00 00 00 push 0x0
40034b: e9 00 00 00 00 jmp 400350 <.plt+0x40>
400350: ff 25 ca 1c 2c 00 jmp QWORD PTR [rip+0x2c1cca] # 6c2020 <_GLOBAL_OFFSET_TABLE_+0x38>
400356: 68 00 00 00 00 push 0x0
40035b: e9 00 00 00 00 jmp 400360 <.plt+0x50>
400360: ff 25 c2 1c 2c 00 jmp QWORD PTR [rip+0x2c1cc2] # 6c2028 <_GLOBAL_OFFSET_TABLE_+0x40>
400366: 68 00 00 00 00 push 0x0
40036b: e9 00 00 00 00 jmp 400370 <.plt+0x60>
400370: ff 25 ba 1c 2c 00 jmp QWORD PTR [rip+0x2c1cba] # 6c2030 <_GLOBAL_OFFSET_TABLE_+0x48>
400376: 68 00 00 00 00 push 0x0
40037b: e9 00 00 00 00 jmp 400380 <.plt+0x70>
400380: ff 25 b2 1c 2c 00 jmp QWORD PTR [rip+0x2c1cb2] # 6c2038 <_GLOBAL_OFFSET_TABLE_+0x50>
400386: 68 00 00 00 00 push 0x0
40038b: e9 00 00 00 00 jmp 400390 <.plt+0x80>
400390: ff 25 aa 1c 2c 00 jmp QWORD PTR [rip+0x2c1caa] # 6c2040 <_GLOBAL_OFFSET_TABLE_+0x58>
400396: 68 00 00 00 00 push 0x0
40039b: e9 00 00 00 00 jmp 4003a0 <.plt+0x90>
4003a0: ff 25 a2 1c 2c 00 jmp QWORD PTR [rip+0x2c1ca2] # 6c2048 <_GLOBAL_OFFSET_TABLE_+0x60>
4003a6: 68 00 00 00 00 push 0x0
4003ab: e9 00 00 00 00 jmp 4003b0 <.plt+0xa0>
4003b0: ff 25 9a 1c 2c 00 jmp QWORD PTR [rip+0x2c1c9a] # 6c2050 <_GLOBAL_OFFSET_TABLE_+0x68>
4003b6: 68 00 00 00 00 push 0x0
4003bb: e9 00 00 00 00 jmp 4003c0 <.plt+0xb0>
4003c0: ff 25 92 1c 2c 00 jmp QWORD PTR [rip+0x2c1c92] # 6c2058 <_GLOBAL_OFFSET_TABLE_+0x70>
4003c6: 68 00 00 00 00 push 0x0
4003cb: e9 00 00 00 00 jmp 4003d0 <check_one_fd.part.0>
Disassembly of section .text:
00000000004003d0 <check_one_fd.part.0>:
4003d0: 55 push rbp
4003d1: 89 f0 mov eax,esi
4003d3: 89 fd mov ebp,edi
4003d5: 83 e0 03 and eax,0x3
4003d8: bf d8 66 49 00 mov edi,0x4966d8
4003dd: 53 push rbx
4003de: 31 db xor ebx,ebx
4003e0: 48 81 ec 98 00 00 00 sub rsp,0x98
4003e7: ff c8 dec eax
4003e9: b8 e2 66 49 00 mov eax,0x4966e2
4003ee: 0f 94 c3 sete bl
4003f1: 48 0f 45 f8 cmovne rdi,rax
4003f5: 31 d2 xor edx,edx
4003f7: 31 c0 xor eax,eax
4003f9: 48 8d 1c 9d 03 01 00 lea rbx,[rbx*4+0x103]
400400: 00
400401: e8 93 8b 01 00 call 418f99 <__open_nocancel>
400406: 39 e8 cmp eax,ebp
400408: 75 2a jne 400434 <check_one_fd.part.0+0x64>
40040a: 48 89 e2 mov rdx,rsp
.......
```
長到我我找不到main在哪裏,所以我就放棄了
但是我們可以注意到
裡面用的register大多是r開頭,這是64 bit register的開頭
讓人覺得這是個64 bit程式,用`file`看看吧
```shell
$ file flag
flag: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.24, BuildID[sha1]=96ec4cc272aeb383bd9ed26c0d4ac0eb5db41b16, not stripped
```
恩他確實是
來用gdb吧
(順帶一提,我這裡使用的是有裝peda plugin的,所以看起來會跟純的gdb有點不一樣)
```shell
$ gdb flag
GNU gdb (Ubuntu 8.2-0ubuntu1~18.04) 8.2
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
gdb-peda$
```
gdb使用`b`指令來下斷點(breakpoint)
我們先在main下個斷點吧
```shell
gdb-peda$ b main
Breakpoint 1 at 0x401168
```
很幸運的成功了
使用`r`讓程式跑起來
```shell
gdb-peda$ r
Starting program: /home/secminhr/flag
[----------------------------------registers-----------------------------------]
RAX: 0x7fffffffe490 --> 0x401ae0 (<__libc_csu_fini>: push rbx)
RBX: 0x401ae0 (<__libc_csu_fini>: push rbx)
RCX: 0x0
RDX: 0x7fffffffe568 --> 0x7fffffffe79a ("LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc"...)
RSI: 0x7fffffffe558 --> 0x7fffffffe786 ("/home/secminhr/flag")
RDI: 0x1
RBP: 0x7fffffffe460 --> 0x0
RSP: 0x7fffffffe460 --> 0x0
RIP: 0x401168 (<main+4>: sub rsp,0x10)
R8 : 0x40 ('@')
R9 : 0xb ('\x0b')
R10: 0xd ('\r')
R11: 0x800
R12: 0x401a50 (<__libc_csu_init>: push r14)
R13: 0x0
R14: 0x0
R15: 0x0
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x401163 <frame_dummy+67>: nop
0x401164 <main>: push rbp
0x401165 <main+1>: mov rbp,rsp
=> 0x401168 <main+4>: sub rsp,0x10
0x40116c <main+8>: mov edi,0x496658
0x401171 <main+13>: call 0x402080 <puts>
0x401176 <main+18>: mov edi,0x64
0x40117b <main+23>: call 0x4099d0 <malloc>
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffe460 --> 0x0
0008| 0x7fffffffe468 --> 0x401344 (<__libc_start_main+404>: mov edi,eax)
0016| 0x7fffffffe470 --> 0x0
0024| 0x7fffffffe478 --> 0x100000000
0032| 0x7fffffffe480 --> 0x7fffffffe558 --> 0x7fffffffe786 ("/home/secminhr/flag")
0040| 0x7fffffffe488 --> 0x401164 (<main>: push rbp)
0048| 0x7fffffffe490 --> 0x401ae0 (<__libc_csu_fini>: push rbx)
0056| 0x7fffffffe498 --> 0x0
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Breakpoint 1, 0x0000000000401168 in main ()
```
中間`[-------------------------------------code-------------------------------------]`
的地方就是,嗯,code
但是只能看到執行的附近幾行而已
我們可以用`disas`(代表disassemble反編譯)來看看完整的main
```shell
gdb-peda$ disas main
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 <puts>
0x0000000000401176 <+18>: mov edi,0x64
0x000000000040117b <+23>: call 0x4099d0 <malloc>
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.
```
那個箭頭很好心的告訴我們現在停在哪一行上
我們可以明明白白地看到有一行寫著`<flag>`
怎麼好意思放過他
打個斷點在他身上
```shell
gdb-peda$ b *0x0000000000401184
Breakpoint 2 at 0x401184
```
然後用`c`(代表continue)來讓程式繼續
```shell
gdb-peda$ c
Continuing.
I will malloc() and strcpy the flag there. take it.
[----------------------------------registers-----------------------------------]
RAX: 0x6c96b0 --> 0x0
RBX: 0x401ae0 (<__libc_csu_fini>: push rbx)
RCX: 0x8
RDX: 0x6c27c0 --> 0x100000000
RSI: 0x0
RDI: 0x4
RBP: 0x7fffffffe460 --> 0x0
RSP: 0x7fffffffe450 --> 0x401a50 (<__libc_csu_init>: push r14)
RIP: 0x401184 (<main+32>: mov rdx,QWORD PTR [rip+0x2c0ee5] # 0x6c2070 <flag>)
R8 : 0x1
R9 : 0x3
R10: 0x22 ('"')
R11: 0x0
R12: 0x401a50 (<__libc_csu_init>: push r14)
R13: 0x0
R14: 0x0
R15: 0x0
EFLAGS: 0x206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x401176 <main+18>: mov edi,0x64
0x40117b <main+23>: call 0x4099d0 <malloc>
0x401180 <main+28>: mov QWORD PTR [rbp-0x8],rax
=> 0x401184 <main+32>: mov rdx,QWORD PTR [rip+0x2c0ee5] # 0x6c2070 <flag>
0x40118b <main+39>: mov rax,QWORD PTR [rbp-0x8]
0x40118f <main+43>: mov rsi,rdx
0x401192 <main+46>: mov rdi,rax
0x401195 <main+49>: call 0x400320
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffe450 --> 0x401a50 (<__libc_csu_init>: push r14)
0008| 0x7fffffffe458 --> 0x6c96b0 --> 0x0
0016| 0x7fffffffe460 --> 0x0
0024| 0x7fffffffe468 --> 0x401344 (<__libc_start_main+404>: mov edi,eax)
0032| 0x7fffffffe470 --> 0x0
0040| 0x7fffffffe478 --> 0x100000000
0048| 0x7fffffffe480 --> 0x7fffffffe558 --> 0x7fffffffe787 ("/home/secminhr/flag")
0056| 0x7fffffffe488 --> 0x401164 (<main>: push rbp)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Breakpoint 2, 0x0000000000401184 in main ()
```
大概可以猜就是把flag有關的東東移到rdx
用`ni`(代表next instruction)執行這一行指令
```shell
gdb-peda$ ni
[----------------------------------registers-----------------------------------]
RAX: 0x6c96b0 --> 0x0
RBX: 0x401ae0 (<__libc_csu_fini>: push rbx)
RCX: 0x8
RDX: 0x496628 ("UPX...? sounds like a delivery service :)")
RSI: 0x0
RDI: 0x4
RBP: 0x7fffffffe460 --> 0x0
RSP: 0x7fffffffe450 --> 0x401a50 (<__libc_csu_init>: push r14)
RIP: 0x40118b (<main+39>: mov rax,QWORD PTR [rbp-0x8])
R8 : 0x1
R9 : 0x3
R10: 0x22 ('"')
R11: 0x0
R12: 0x401a50 (<__libc_csu_init>: push r14)
R13: 0x0
R14: 0x0
R15: 0x0
EFLAGS: 0x206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x40117b <main+23>: call 0x4099d0 <malloc>
0x401180 <main+28>: mov QWORD PTR [rbp-0x8],rax
0x401184 <main+32>: mov rdx,QWORD PTR [rip+0x2c0ee5] # 0x6c2070 <flag>
=> 0x40118b <main+39>: mov rax,QWORD PTR [rbp-0x8]
0x40118f <main+43>: mov rsi,rdx
0x401192 <main+46>: mov rdi,rax
0x401195 <main+49>: call 0x400320
0x40119a <main+54>: mov eax,0x0
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffe450 --> 0x401a50 (<__libc_csu_init>: push r14)
0008| 0x7fffffffe458 --> 0x6c96b0 --> 0x0
0016| 0x7fffffffe460 --> 0x0
0024| 0x7fffffffe468 --> 0x401344 (<__libc_start_main+404>: mov edi,eax)
0032| 0x7fffffffe470 --> 0x0
0040| 0x7fffffffe478 --> 0x100000000
0048| 0x7fffffffe480 --> 0x7fffffffe558 --> 0x7fffffffe787 ("/home/secminhr/flag")
0056| 0x7fffffffe488 --> 0x401164 (<main>: push rbp)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
0x000000000040118b in main ()
```
往上看看rdx,flag到手
sumbit,通過,開心
2021-01-23 16:45:03
留言
Last fetch: --:--
現在還沒有留言!