堆栈解题练习二

解题准备知识:

查询通解的思路:
1.同一个模块内,代码段和数据段之间的距离确定,不受随机化影响
2.同一动态库内,每个函数在动态库内部的偏移量是确定的
3.只要泄露出动态库中某个函数的地址,就可以知道该函数在动态库中的偏移。
4.不同动态库中相同函数的偏移量是不同的,那就可以通过这个泄露的偏移量确定该程序使用的动态库的版本。
5.计算出动态库的基址:动态库的基址=泄露的函数的地址 - 该函数在动态库中的偏移量
6.计算出system函数的地址:system函数的地址= 动态库的基址 + system函数在动态库中的偏移量
7.找到 /bin/sh 这个字符串的所在位置,一般动态库里有这个字符串
8.如果没有这个字符串就使用能写入的函数,将这个字符串读写到可写入的区域,这就需要构造ROP链,pop pop pop ret 。
参考博文:https://blog.csdn.net/qq_43394612/article/details/85323020

首先检测程序开启的保护

hu@ubuntu:~/Desktop/stack over$ checksec pwn3
[*] '/home/hu/Desktop/stack over/pwn3'
Arch:     amd64-64-little
RELRO:    Partial RELRO
Stack:    No canary found
NX:       NX enabled
PIE:      No PIE (0x400000)

可以看出,源程序为 64 位,开启了 NX和ASLR 保护。

利用 IDA 来查看源码

int __cdecl main(int argc, const char **argv, const char **envp)
{
 char buf; // [rsp+0h] [rbp-40h]
 puts("Welcome to the stack training_3");
 puts("Now play your game: ");
 read(0, &buf, 0x150uLL);
 return 0;
 }

可以看到 buf 这个字符串数组只有0x40的大小,但是却可以 read 0x150个字节,多出来的 0x150-0x80 就会造成溢出.
因为程序中没有可以直接利用的代码,也不能自己填写代码来获得 shell,所以我们利用程序中的 gadgets 来获得 shell

首先绕过ASLR(地址随机化),泄露出libc的基址libc_base,然后利用构造ROP链绕过NX,这两步要在一次运行完成,不然因为地址随机化的缘故,在下一次运行时libc基址又将改变。

查看共享库:
在这里插入图片描述
运行三次,每次加载位置都不同,即不可通过简单的ldd命令查看共享库将libc的加载地址给获取。
把libc.so.6复制到当前目录下,可见它偏移量:

   hu@ubuntu:~/Desktop/stackstack$ one_gadget libc.so.6
   0x45216 execve("/bin/sh", rsp+0x30, environ)
   constraints: rax == NULL
   0x4526a execve("/bin/sh", rsp+0x30, environ)
   constraints: [rsp+0x30] == NULL
   0xf02a4 execve("/bin/sh", rsp+0x50, environ)
   constraints: [rsp+0x50] == NULL
   0xf1147 execve("/bin/sh", rsp+0x70, environ)
   constraints: [rsp+0x70] == NULL

在IDA中可以找到main函数入口地址为:

.text:0000000000400566 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:0000000000400566                 public main
.text:0000000000400566 main            proc near               ; DATA XREF: _start+1D↑o
.text:0000000000400566
.text:0000000000400566
.text:0000000000400566 buf             = byte ptr -40h
.text:0000000000400566
.text:0000000000400566 ; __unwind {
.text:0000000000400566                 push    rbp
.text:0000000000400567                 mov     rbp, rsp
.text:000000000040056A                 sub     rsp, 40h
.text:000000000040056E                 mov     edi, offset aWelcomeToTheSt ; "Welcome to the stack training_3"
.text:0000000000400573                 call    _puts
.text:0000000000400578                 mov     edi, offset aNowPlayYourGam ; "Now play your game: "
.text:000000000040057D                 call    _puts
.text:0000000000400582                 lea     rax, [rbp+buf]
.text:0000000000400586                 mov     edx, 150h       ; nbytes
.text:000000000040058B                 mov     rsi, rax        ; buf
.text:000000000040058E                 mov     edi, 0          ; fd
.text:0000000000400593                 call    _read
.text:0000000000400598                 mov     eax, 0
.text:000000000040059D                 leave
.text:000000000040059E                 retn
.text:000000000040059E ; } // starts at 400566
.text:000000000040059E main            endp

put与read在got表中的地址为:

.got.plt:0000000000601018 off_601018      dq offset puts          ; DATA XREF: _puts↑r
.got.plt:0000000000601020 off_601020      dq offset read          ; DATA XREF: _read↑r

put在plt表中的地址为:

  .plt:0000000000400430 ; 
  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值