來自戰隊:@驢肉火燒python
簽到
附件下載c++
題目給出一張圖片,提示觀色,預計多是將信息隱藏在某一色道中或 LSB 隱寫
將給出的圖片導入 StegSolve.jar,在 red plane 1 中發現半個 flag
算法
利用 Frame Browser 對圖片進一步分析能夠分離出第二張圖片,數組
一樣在 red plane 1 中發現另外半個 flag緩存
熟悉的解密
附件下載app
附件壓縮包裏面是一個文本文件,很明顯是數行用 base64 編碼的字符串ui
寫以下腳本進行解碼:編碼
import base64 f1 = open('1.txt', 'r') f2 = open('2.py', 'w') line = f1.readline() while line: str = base64.b64decode(line).decode('utf-8') f2.write(str) line = f1.readline() f1.close() f2.close()
獲得:加密
#!/usr/bin/env python #-*- coding: utf-8 -*- import sys from ctypes import * def encipher(v, k): y = c_uint32(v[0]) z = c_uint32(v[1]) sum = c_uint32(0) delta = 0x9e3779b9 n = 32 w = [0,0] while(n>0): sum.value += delta y.value += ( z.value << 4 ) + k[0] ^ z.value + sum.value ^ ( z.value >> 5 ) + k[1] z.value += ( y.value << 4 ) + k[2] ^ y.value + sum.value ^ ( y.value >> 5 ) + k[3] n -= 1 w[0] = y.value w[1] = z.value return w def encodestr(text, key): cipherList = [] text += (8 - len(text) % 8) * chr(0) for i in range(len(text)/8): v1 = 0 v2 = 0 for j in range(4): v1+= ord(text[i*8+j]) << (4-j-1)*8 v2+= ord(text[i*8+j+4]) << (4-j-1)*8 cipherList.append(encipher([v1,v2],key)) return cipherList if __name__ == "__main__": key = [11,22,33,44] flag = ? cipher = encodestr(flag1,key) #cipher = [[4018289233L, 2950320151L], [1771827478L, 493980876L], [1863284879L, 1137797599L], [2759701525L, 3957885055L], [2600866805L, 78850724L]]
程序的邏輯是將 flag 進行 encipher() 和 encodestr() 雙重加密獲得五組由兩個整數組成的列表spa
由內向外來看,encipher() 裏面有一個常數 0x9e3779b9,是利用 TEA 算法進行分組加密,因爲 key 恆定,因此能夠寫出逆算法解密
void decrypt (uint32_t* v, uint32_t* k) { uint32_t v0=v[0], v1=v[1], sum=0xC6EF3720, i; uint32_t delta=0x9e3779b9; uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; for (i=0; i<32; i++) { v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3); v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1); sum -= delta; } v[0]=v0; v[1]=v1; }
獲得五組數據:
1718378855 2067085111 859137328 1663907428 808594737 828727597 942683954 758133808 1694498816 0
encodestr() 的核心大意是把一個字符串拆成八段,v1 和 v2 分別對每小段的先後部分的 ASCALL 位移後進行累加,最後拿去 encipher() 加密
此時咱們已經知道 encipher() 加密前的數據,考慮逆向還原到字符
一個字符正好佔用 1kb(8b),因此位移操做(位移數爲 8 的倍數)仍舊使得每一位字符的摘要獨立,每四位拆開再從頭到尾拼接便可
exp 以下:
#include <bits/stdc++.h> using namespace std; int List[5][2]= {{1718378855,2067085111}, {859137328,1663907428},{808594737,828727597}, {942683954,758133808},{1694498816,0}}; int main() { for (int i=0;i<5;i++) { int now=List[i][0]; for (int j=0;j<4;j++) { printf("%c",now>>(8*(3-j))); now-=(now>>(8*(3-j)))<<(8*(3-j)); } now=List[i][1]; for (int j=0;j<4;j++) { printf("%c",now>>(8*(3-j))); now-=(now>>(8*(3-j)))<<(8*(3-j)); } } return 0; }
跑出來仍是少了後面的一部分,考慮有對原始文本進行過 base64 隱寫,另寫腳本找出剩下的內容:
import base64 b64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' with open('1.txt', 'rb') as f: flag = '' bin_str = '' for line in f.readlines(): stegb64 = str(line, "utf-8").strip("\n") rowb64 = str(base64.b64encode(base64.b64decode(stegb64)), "utf-8").strip("\n") offset = abs(b64chars.index(stegb64.replace('=','')[-1]) - b64chars.index(rowb64.replace('=','')[-1])) equalnum = stegb64.count('=') #no equalnum no offset if equalnum: bin_str += bin(offset)[2:].zfill(equalnum * 2) print([chr(int(bin_str[i:i + 8], 2)) for i in range(0, len(bin_str), 8)])
拼接以後就是完整的 flag 了
flag{57735e0c-6d02-11ea-8072-040e3c032fa7}
sudo
沒有附件,能夠遠程鏈接到數獨程序
一開始懷疑是盲打 pwn,手工輸入了長長的字符串,提示 invalid input! 沒有發生緩存區溢出
此外程序有個 alarm(),一小段時間無操做就會自動結束進程,這時候知道真的要作數獨了
(1~9)*81 的意思就是要輸入 81 個由數字 1~9 組成的字符,從上至下,從左至右填滿數獨棋盤
思路也比較簡單,用 pwntools 模塊收發信息,稍微進行清洗以後丟給(暴力)算法求解
exp 以下:
#coding=utf-8 from pwn import * import datetime payload = '' class solution(object): # 數獨類,帶求解算法 def __init__(self,board): self.b = board self.t = 0 def check(self,x,y,value): for row_item in self.b[x]: if row_item == value: return False for row_all in self.b: if row_all[y] == value: return False row,col=x/3*3,y/3*3 row3col3=self.b[row][col:col+3]+self.b[row+1][col:col+3]+self.b[row+2][col:col+3] for row3col3_item in row3col3: if row3col3_item == value: return False return True def get_next(self,x,y): for next_soulu in range(y+1,9): if self.b[x][next_soulu] == 0: return x,next_soulu for row_n in range(x+1,9): for col_n in range(0,9): if self.b[row_n][col_n] == 0: return row_n,col_n return -1,-1 def try_it(self,x,y): if self.b[x][y] == 0: for i in range(1,10): self.t+=1 if self.check(x,y,i): self.b[x][y]=i next_x,next_y=self.get_next(x,y) if next_x == -1: return True else: end=self.try_it(next_x,next_y) if not end: self.b[x][y] = 0 else: return True def start(self): global payload begin = datetime.datetime.now() if self.b[0][0] == 0: self.try_it(0,0) else: x,y=self.get_next(0,0) self.try_it(x,y) for i in self.b: print i for j in i: payload += str(j) end = datetime.datetime.now() print '\ncost time:', end - begin print 'times:',self.t return io = remote('47.93.204.245', '12000') for i in range(3): payload = '' List = [[], [], [], [], [], [], [], [], []] for i in range(9): st = io.recvline() st = st.replace('#', '0') st = st.replace(' ', '')[:-1] print st for j in st: List[i].append(int(j)) print List s=solution(List) s.start() print 'payload: '+ payload io.recvuntil('input your answer[ (1~9)*81 ]:\n') io.sendline(payload) #print io.recv() #io.interactive() io.recvuntil('Congratulation!') io.interactive()