来自战队:@驴肉火烧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()