讚賞碼 & 聯繫方式 & 個人閒話
逆向工程前言
Pre1
1.(一定要看)閱讀Python Tutorial。
會大致看懂基本語法能完成下個任務就可以了,不要求學會這門語言
http://www.pythondoc.com/pythontutorial3/index.html
2.Python實現Base64
搜索Base64算法資料,詳細解釋該算法。用Python實現它,把自己的學號(字母大寫)用Base64編碼輸出。並且把上面的源代碼文件編譯成pyc文件。(不要抄襲)
代碼:
#Base64的索引與對應字符的關係
Base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
#待編碼字符
STR="E41614018"
#轉化成list方便處理缺失字節情況
Str=list(STR)
print("明文: "+STR)
print("Base64:", end='')
#每組三個字符即3*8=24bit,轉換爲
for i in range(0,len(Str),3):
a=ord(Str[i])
#若缺2字節
if len(Str)-1==i:
b=0;
else:
b=ord(Str[i+1])
#若缺1or2字節
if (len(Str)-1==i)|(len(Str)-2==i):
c=0;
else:
c=ord(Str[i+2])
#拆成4個6bit,計算各自的索引號
A= a>>2
B=((a&0b00000011)<<4)+((b&0b11110000)>>4)
C=((b&0b00001111)<<2)+((c&0b11000000)>>6)
D= c&0b00111111
#根據索引在Base64尋找,並輸出對應字符
#若缺2字節
if len(Str)-1==i:
print(Base64[A]+Base64[B]+'==', end='')
else:
#若缺1字節
if (len(Str)-2==i):
print(Base64[A]+Base64[B]+Base64[C]+'=', end='')
else:
#若不缺字節
print(Base64[A]+Base64[B]+Base64[C]+Base64[D], end='')
print("\n")
運行結果:
輸出內容:
明文: E41614018
Base64:RTQxNjE0MDE4
小結與討論:
Base64編碼算法能夠將任意的字節數組數據,通過算法參照“Base64編碼索引表”生成只有“大小寫英文字母、數字、+、/”(共64個字符)內容表示的字符串數據,即將任意的內容轉換爲可見的字符串形式。
Base64算法在編碼時將數據按照3個字節一組的形式進行處理,每3個字節在編碼之後被轉換爲4個字節。而當數據的長度無法滿足3的倍數的情況下,最後的數據需要進行填充操作,即補“=” (這裏“=”是填充字符表示沒有數據,而不是上述64個字符中包含的字符)。
這裏需要注意的是:Base64是編碼算法而不是加密算法,只是用來編碼字節數組形成字符串的。Base64算法提供瞭解碼功能,並且任何人都可以將Base64的編碼結果解碼成唯一的原文。
3.反編譯
找班上學號和你相鄰的一位同學要一下上面的pyc文件(不是源代碼文件),然後搜索相關反編譯工具把pyc反編譯成Python源代碼,最好能多找幾種工具或者途徑達到反編譯的目的。
①在線反編譯平臺:https://tool.lu/pyc/:
②Python反編譯工具---Easy Python Decompiler:
反編譯失敗,系統提示:Magic value mismatch魔法值不匹配。這是因爲它只支持python2.7與python3.4以下的版本。
③在線反編譯平臺http://tools.bugscaner.com/decompyle/
4.Cracking SHA1-Hashed Passwords
去https://www.mysterytwisterc3.org/用組長的學號註冊一個賬號(字母大寫),
註冊的時候有個Captcha可能要FQ才能顯示,賬號密碼記住以後課堂要用到。
完成關卡Cracking SHA1-Hashed Passwords。
https://www.mysterytwisterc3.org/en/challenges/level-ii/cracking-sha1-hashed-passwords
代碼:
import hashlib
import copy
#遞歸求解1-8的全排列
def permutation(lst,k):
result = []
length = len(lst)
tmp = [0]*k
def next_num(a,ni=0):
if ni == k:
result.append(copy.copy(tmp))
return
for lj in a:
tmp[ni] = lj
b = a[:]
b.pop(a.index(lj))
next_num(b,ni+1)
c = lst[:]
next_num(c,0)
return result
P=permutation([1,2,3,4,5,6,7,8],8)
SS = [[0 for i in range(4)] for i in range(9)]
S = [[0 for i in range(4)] for i in range(9)]
#放入所有可能選擇
SS[1][1]="Q"
SS[1][2]="q"
SS[2][1]="W"
SS[2][2]="w"
SS[3][1]="I"
SS[3][2]="i"
SS[4][1]="N"
SS[4][2]="n"
SS[5][1]="%"
SS[5][2]="5"
SS[6][1]="("
SS[6][2]="8"
SS[6][3]="["
SS[7][1]="="
SS[7][2]="0"
SS[7][3]="}"
SS[8][1]="*"
SS[8][2]="+"
SS[8][3]="~"
flag=0;
#print(len(P),len(P[1]))
#遍歷每一種排列情況
for i in range(len(P)):
if flag==1:
break;
#根據排列組成S
for j in range(len(P[1])):
if flag==1:
break;
S[j+1]=SS[P[i][j]]
sha1=""
#print(S)
#對於每種排列,每個鍵又有2、3種選擇
#遍歷所有選擇
for a in range(1,4):
#已經找到則退出
if flag==1:
break;
#遇到爲0的選項則跳過該可能
if S[1][a]==0:
continue
for b in range(1,4):
if flag==1:
break;
if S[2][b]==0:
continue
for c in range(1,4):
if flag==1:
break;
if S[3][c]==0:
continue
for d in range(1,4):
if flag==1:
break;
if S[4][d]==0:
continue
for e in range(1,4):
if flag==1:
break;
if S[5][e]==0:
continue
for f in range(1,4):
if flag==1:
break;
if S[6][f]==0:
continue
for g in range(1,4):
if flag==1:
break;
if S[7][g]==0:
continue
for h in range(1,4):
if flag==1:
break;
if S[8][h]==0:
continue
string=S[1][a]+S[2][b]+S[3][c]+S[4][d]+S[5][e]+S[6][f]+S[7][g]+S[8][h]
#計算sha1值
sha1=hashlib.sha1(string.encode('utf-8'))
#print(sha1.hexdigest())
#若相同則輸出對應密碼
if sha1.hexdigest()=='67ae1a64661ac8b4494666f58c4822408dd0a3e4':
print('We found it : '+S[1][a]+S[2][b]+S[3][c]+S[4][d]+S[5][e]+S[6][f]+S[7][g]+S[8][h])
print(sha1.hexdigest())
flag=1
運行結果:
結果驗證:
密碼:(Q=win*5
將密碼提交到網站上,提示已經成功解題:
小結與討論:
本題我們求解的基本思路還是暴力破解。仔細觀察題目所給輸入密碼的鍵盤圖:
考慮到題目應是短時間內可解的,所以我們做出如下的假設來減少計算量(後來得出的密碼也證明假設是合理的)
(1)真正作爲密碼輸入的應該只有Q、W、5、8、0、I、N、+這8個鍵(當然每個鍵會有不同的輸入),shift鍵、方向鍵和右側數字鍵都只做到控制作用,並沒有實際的字符輸入;
(2)不考慮重複按鍵的情況,否則該問題將無法求解。
於是,我們可以得到如下思路:
①由於我們未知這8個鍵的敲擊順序,我們要找出其全排列,易知爲8的階乘種;
②其次對於每一種排列情況又會有不同的字符組合,同一個鍵,如+鍵,可以輸入“+”、“-”、“*”這3種字符。即使對Q之類的字母鍵也會有“Q”與“q”的區別,所以我們要對這些不同的字符組合進行遍歷;
③對於每一種字符組合我們利用hashlib庫來計算其sha1值與我們的目的sha1值進行比較,若相同則說明密碼已經找到,即破解成功。
5.4B58475789E60DBF1A28GD638B556A938134644C8
從前有一個熊孩子入侵了一個網站的數據庫,找到了管理員密碼,手一抖在數據庫中修改了一下:
現在的密碼變成4B58475789E60DBF1A28GD638B556A938134644C8。
那個熊孩子其實就是我!腫麼辦求解原始密碼!在線等,挺急的。
hint:密碼長度爲5
代碼:
import hashlib
import copy
#遞歸求解0-4的全排列
def permutation(lst,k):
result = []
length = len(lst)
tmp = [0]*k
def next_num(a,ni=0):
if ni == k:
result.append(copy.copy(tmp))
return
for lj in a:
tmp[ni] = lj
b = a[:]
b.pop(a.index(lj))
next_num(b,ni+1)
c = lst[:]
next_num(c,0)
return result
flag=0;
P=permutation([0,1,2,3,4],5)
#print(P)
#所有字符
SS=['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7','8','9']
#通過五次循環從字符池中挑選出5個字符(因爲題目給出密碼爲5位)
for a in range(len(SS)-4):
if flag==1:
break
for b in range(1,len(SS)-3):
if flag==1:
break
for c in range(2,len(SS)-2):
if flag==1:
break
for d in range(3,len(SS)-1):
if flag==1:
break
for e in range(4,len(SS)):
if flag==1:
break
S=SS[a]+SS[b]+SS[c]+SS[d]+SS[e]
#對於挑選出的5個字符,進行全排列
for i in range(len(P)):
s=S[P[i][0]]+S[P[i][1]]+S[P[i][2]]+S[P[i][3]]+S[P[i][4]]
sha1=hashlib.sha1(s.encode('utf-8'))
#print(sha1.hexdigest())
#若相同則輸出對應密碼
if sha1.hexdigest()=='4b58475789e60dbf1a28d638b556a938134644c8':
print('We found it : '+s)
print(sha1.hexdigest())
flag=1
break
運行結果:
小結與討論:
本題的解題思路和第4題相似,首先我們很容易看出字符“G”是多餘的,將其去除。接下來就是暴力破解了,暴力的方法就是從我們設定的字符池裏面挑選出5個字符(因爲題目給出密碼爲5位),再把挑選出的5個字符進行全排列。代碼編寫時我們利用了上一題的部分代碼並進行了修改。
最後求解得密碼爲:BSWAP。至此,實驗順利完成。