逆向工程實驗Pre1

讚賞碼 & 聯繫方式 & 個人閒話

逆向工程前言

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。至此,實驗順利完成。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章