気まぐれブログ(日記・技術記事・研究のことなど)

気まぐれに更新します.温かい目で見ていただければ...

"flag" 「UPXとは」

pwnableの問題を解き進めていたところ, 「UPX」を使用する問題に出会いました. UPXについて何も知らなかったので, writeupがてらUPXについて調べたことをまとめておこうと思います.

問題

http://pwnable.kr/play.php

バイナリファイルのみ与えられて, そこからflagを見つけ出してねっていう問題.

解説

まずはfileコマンドを打ち込んでみましょう.

$ file flag
flag: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, stripped

どうやらシンボル情報が削除されているらしい. まずはここで面食らう.

続いて逆アセンブルしてみましょう.

$ objdump -d -M intel flag

flag:     ファイル形式 elf64-x86-64

むむっ!!何も表示されない...これは困りましたね...

とりあえずstringsコマンドでも打っておきましょうか.

$ strings flag
UPX!
@/x8
gX lw_
H/\_@
	Kl$
H9\$(t
[]]y
nIV,Uh
AWAVAUATS
uSL9
>t		.
[A\AA;h
]A^A_*U
A4tV

.... (中略)


L#EK
@Bh]
Ixun
;dl]tpR
c3Rh
2B)=	
1\a}
_M]h
Upbrk
makBN
su`"]R
UPX!
UPX!

すげえ量が出力されるんですが, そのなかに気になる文章を発見!!!

$Info: This file is packed with the UPX executable packer http://upx.sf.net $
$Id: UPX 3.08 Copyright (C) 1996-2011 the UPX Team. All Rights Reserved. $

どうやら「UPX」というもので圧縮されたファイルみたい. じゃあ解凍してやればおkですね.
解凍方法はググって出てきたものを再利用.

$ upx -d flag -o unpack_flag

これでunpack_flagに解凍されたファイルが出力されました. あとはunpack_flagをデバックしてやれば良さそうですね.

$ gdb -q unpack_flag
Reading symbols from unpack_flag...(no debugging symbols found)...done.
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.
gdb-peda$ b *main+32
Breakpoint 1 at 0x401184
gdb-peda$ r

...


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: 0x7fffffffdf70 --> 0x0 
RSP: 0x7fffffffdf60 --> 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: 0x202 (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| 0x7fffffffdf60 --> 0x401a50 (<__libc_csu_init>:	push   r14)
0008| 0x7fffffffdf68 --> 0x6c96b0 --> 0x0 
0016| 0x7fffffffdf70 --> 0x0 
0024| 0x7fffffffdf78 --> 0x401344 (<__libc_start_main+404>:	mov    edi,eax)
0032| 0x7fffffffdf80 --> 0x0 
0040| 0x7fffffffdf88 --> 0x100000000 
0048| 0x7fffffffdf90 --> 0x7fffffffe068 --> 0x7fffffffe399 ("/home/hirata/pwnable/4/unpack_flag")
0056| 0x7fffffffdf98 --> 0x401164 (<main>:	push   rbp)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
0x000000000040118b in main ()

RDXにflagが存在してますね.

ところでUPXってなに?

問題が解けたのはいいのですが, UPXってなんぞや?

気になったので調べました.


UPXとは, 様々なOSのファイル形式に対応した実行ファイル圧縮ソフトらしい. UCLと呼ばれるデータ圧縮アルゴリズムを使用していて, このUCLは数百バイトで実装できるようなシンプルな設計になっているそうです. 素敵ですね.

圧縮率はだいたい35~45%ほど. UPXを使うメリットとしては, 起動の高速化などが挙げられます.