<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    [Rev賽題復現]DASCTF Apr X FATE 2022

    VSole2022-06-25 16:10:15

    Crackme

    幾個關鍵點:mfc逆向,win32 加密api的識別,ZwSetInformationThread反調試。

    看程序圖標是個mfc的程序,先打開看看,隨便輸入一點東西,看到彈窗彈出:

    直接拖進ida搜索Wrong!!!字符串,借此通過查看引用跳轉到主函數。

    先簡單的修復一下變量名:

    大概可以看到key的前4位經過一次sub_403510,后4位也經過一次sub_403510,整個key8位又經過一次sub_403510。

    隨后進入sub_403510函數看一看,看到有一堆為win32 加密api的函數。

    那就對照著MSDN一個個函數查閱一下:

    CryptAcquireContext 函數用于獲取特定加密服務提供程序 (CSP) 中特定密鑰容器的句柄。此返回的句柄用于調用使用所選 CSP 的 CryptoAPI 函數。

    BOOL CryptAcquireContextA([out] HCRYPTPROV *phProv,[in]  LPCSTR     szContainer,[in]  LPCSTR     szProvider,[in]  DWORD      dwProvType,[in]  DWORD      dwFlags);
    

    CryptCreateHash 函數啟動數據流的哈希。它創建加密服務提供程序 (CSP) 哈希對象的句柄并將其返回給調用應用程序。此句柄用于對 CryptHashData 和 CryptHashSessionKey 的后續調用,以哈希會話密鑰和其他數據流。

    BOOL CryptCreateHash([in]  HCRYPTPROV hProv,[in]  ALG_ID     Algid,[in]  HCRYPTKEY  hKey,[in]  DWORD      dwFlags,[out] HCRYPTHASH *phHash);
    

    注意這里Algid是標識要使用的哈希算法的參數,通過不同的值的傳入選擇不同的hash算法,可查下面的鏈接:ALG_ID (Wincrypt.h) - Win32 apps | Microsoft Docs(https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id

    CryptHashData 函數將數據添加到指定的哈希對象。此函數和CryptHashSessionKey可以多次調用,以計算長數據流或不連續數據流的哈希值。

    BOOL CryptHashData([in] HCRYPTHASH hHash,[in] const BYTE *pbData,[in] DWORD      dwDataLen,[in] DWORD      dwFlags);
    

    CryptGetHashParam 函數檢索控制哈希對象操作的數據。可以使用此函數檢索實際的哈希值。

    BOOL CryptGetHashParam([in]      HCRYPTHASH hHash,[in]      DWORD      dwParam,[out]     BYTE       *pbData,[in, out] DWORD      *pdwDataLen,[in]      DWORD      dwFlags);
    

    CryptEncrypt 函數對數據進行加密。用于加密數據的算法由 CSP 模塊持有的密鑰指定,并由 hKey 參數引用。

    BOOL CryptEncrypt([in]      HCRYPTKEY  hKey,[in]      HCRYPTHASH hHash,[in]      BOOL       Final,[in]      DWORD      dwFlags,[in, out] BYTE       *pbData,[in, out] DWORD      *pdwDataLen,[in]      DWORD      dwBufLen);
    

    程序大概的邏輯就是這樣:

    然后我們就通過動調去拿數據,這里有兩種方式,一種是通過ida patch反調試函數的方式,一種是通過od 的sharp od插件直接繞過。

    繞反調試方法一:先用ida繞過反調試

    對比各種反調試和去IAT表找導入函數沒有找到,后面在strings界面可以發現ZwSetInformationThread反調試的特征ZwSetInformationThread - CTF Wiki (ctf-wiki.org)(https://ctf-wiki.org/reverse/windows/anti-debug/zwsetinformationthread/

    ZwSetInformationThread通過為線程設置 ThreadHideFromDebugger,可以禁止線程產生調試事件。

    繞過: ZwSetInformationThread 函數的第 2 個參數為 ThreadHideFromDebugger,其值為 0x11。調試執行到該函數時,若發現第 2 個參數值為 0x11,跳過或者將 0x11 修改為其他值即可。

    看來是自己實現調用dll導入的。

    類似于這種寫法:

    我們可以先在調用處下一個斷點,跑起來之后再修改patch 0x11 改掉,我這里patch成了0x9。

    然后繼續下斷點拿密文。

    然后再扔到md5解密網站解密。

    類似的拿到sha1解密后的key后四位 https://crackstation.net/

    key:NocTuRne

    md5(key):C0804C74E05B4C7440AC4D7480954C74

    繞反調試方法二:OD odsharp插件直接繞

    之后就是模擬調用win32 的aes解密api來解密的過程了。

    #include #include #include 
    int main(){    BYTE pbData[] = {0x5c,0x53,0xa4,0xa4,0x1d,0x52,0x43,0x7a,0x9f,0xa1,0xe9,0xc2,0x6c,0xa5,0x90,0x90,0x0};  //key_buf    BYTE flag_encrypt[] = {0x5B, 0x9C, 0xEE, 0xB2, 0x3B, 0xB7, 0xD7, 0x34, 0xF3, 0x1B, 0x75, 0x14, 0xC6, 0xB2, 0x1F, 0xE8, 0xDE, 0x33, 0x44, 0x74, 0x75, 0x1B, 0x47, 0x6A, 0xD4, 0x37, 0x51, 0x88, 0xFC, 0x67, 0xE6, 0x60, 0xDA, 0x0D, 0x58, 0x07, 0x81, 0x43, 0x53, 0xEA, 0x7B, 0x52, 0x85, 0x6C, 0x86, 0x65, 0xAF, 0xB4,0x0};    DWORD dwDataLen = 0x10;    DWORD ddwDataLen;    DWORD* pdwDataLen = &ddwDataLen;    *pdwDataLen = 0x20;
        BOOL v6; // [esp+4h] [ebp-18h]    HCRYPTKEY phKey; // [esp+Ch] [ebp-10h] BYREF    HCRYPTPROV phProv; // [esp+10h] [ebp-Ch] BYREF    HCRYPTHASH phHash; // [esp+14h] [ebp-8h] BYREF
        phProv = 0;    phHash = 0;    phKey = 0;    v6 = CryptAcquireContextA(&phProv, 0, 0, 0x18u, 0xF0000000);    if (v6)    {        v6 = CryptCreateHash(phProv, 0x8003u, 0, 0, &phHash);        if (v6)        {            v6 = CryptHashData(phHash, pbData, dwDataLen, 0);            if (v6)            {                v6 = CryptDeriveKey(phProv, 0x660Eu, phHash, 1u, &phKey);// key的md5值再生成aes密鑰                if (v6)                    v6 = CryptDecrypt(phKey, 0, 1, 0, flag_encrypt, pdwDataLen);                    printf("%s", flag_encrypt);            }        }    }    if (phKey)        CryptDestroyKey(phKey);    if (phHash)        CryptDestroyHash(phHash);    if (phProv)        CryptReleaseContext(phProv, 0);    return v6;}
    

    拿到flag!

    補充方法:Hook Windows API 求解

    另外經mas0n師傅補充,附上frida來hook求解的方法。

      var baseAddr = Process.findModuleByName('Crackme_1.exe');
    // input 32 length flag, e.g. 11111111111111111111111111111111// key: NocTuRne// frida attach -p 48964 -l agent\hook_win.js
    // memcmpvar hookAddr = ptr(0x0109D4BC);Interceptor.attach(hookAddr, {    onEnter: function(args) {        let Buf1 = args[0];        let Buf2 = args[1];        let Size = args[2];        console.log("-----[Size]", Size);        let size = Size.toInt32();        console.log("-----[Buf1]", Buf1.readByteArray(size));        console.log("-----[Buf2]", Buf2.readByteArray(size));        console.log("---------------------------");    },    onLeave: function(arg) {        return arg;    }})
    var libAddr = Process.findModuleByName('ADVAPI32.dll');var fn_CryptEncrypt = libAddr.getExportByName("CryptEncrypt");var fn_CryptDecrypt = libAddr.getExportByName("CryptDecrypt");
    var flag = null;Interceptor.replace(fn_CryptEncrypt, fn_CryptDecrypt);Interceptor.attach(fn_CryptDecrypt, {    onEnter: function(args) {        args[4].writeByteArray([0x5b,0x9c,0xee,0xb2,0x3b,0xb7,0xd7,0x34,0xf3,0x1b,0x75,0x14,0xc6,0xb2,0x1f,0xe8,0xde,0x33,0x44,0x74,0x75,0x1b,0x47,0x6a,0xd4,0x37,0x51,0x88,0xfc,0x67,0xe6,0x60,0xda,0x0d,0x58,0x07,0x81,0x43,0x53,0xea,0x7b,0x52,0x85,0x6c,0x86,0x65,0xaf,0xb4]);        args[5].writeInt(0x40);        flag = args[4];        console.log("hook fn_CryptDecrypt");        return args;    },    onLeave: function(arg) {        console.log(flag.readCString());        return arg;    }})
    

    奇怪的交易

    拖進ida里發現經過upx加殼,直接upx -d脫殼。

     

    接著再使用pyinstxtractor解包得到一堆文件(比較坑的地方是本地python環境必須與源程序的python環境相同才能解包PYZ-00.pyz),下面是徹底解包后的幾個關鍵的文件。

    奇怪的交易.pyc文件內容如下:

    python反編譯 - 在線工具 (tool.lu)(https://tool.lu/pyc/

    這樣其實邏輯很明顯還是有問題的,題目特意用的Python3.10版本,導致反編譯結果會不正確。

    通過pycdump可以dump出opcode,對比進行變量名和代碼邏輯的修復。

    可以參考下面的文章:

    Python字節碼文檔 Python字節碼詳解(介紹了Python的特有類型以及遍歷等操作)(https://blog.csdn.net/weixin_46263782/article/details/120930191

    修復后的 奇怪的交易.py

    from cup import *from libnum import *
    if __name__ == '__main__':    flag = input('請輸入flag')    pub_key = [        0x649EE967E7916A825CC9FD3320BEABF263BEAC68C080F52824A0F521EDB6B78577EC52BF1C9E78F4BB71192F9A23F1A17AA76E5979E4D953329D3CA65FB4A71DA57412B59DFD6AEDF0191C5555D3E5F582B81B5E6B23163E9889204A81AFFDF119FE25C92F4ED59BD3285BCD7AAE14824240D2E33C5A97848F4EB7AAC203DE6330D2B4D8FF61691544FBECD120F99A157B3D2F58FA51B2887A9D06CA383C44D071314A12B17928B96F03A06E959A5AFEFA0183664F52CD32B9FC72A04B45913FCB2D5D2D3A415A14F611CF1EAC2D6C785142A8E9CC41B67A6CD85001B06EDB8CA767D367E56E0AE651491BF8A8C17A38A1835DB9E4A9292B1D86D5776C98CC25,        0x647327833ACFEF1F9C83E74E171FC300FA347D4A6769476C33DA82C95120ACB38B62B33D429206FE6E9BB0BB7AB748A1036971BEA36EC47130B749C1C9FF6FE03D0F7D9FC5346EB0E575BDFA6C530AA57CD676894FC080D2DD049AB59625F4B9C78BCFD95CDCD2793E440E26E189D251121CB6EB177FEDB596409034E8B0C5BBD9BD9342235DBB226C9170EFE347FF0FD2CFF9A1F7B647CC83E4D8F005FD7125A89251C768AFE70BDD54B88116814D5030F499BCAC4673CCCC342FB4B6AC58EA5A64546DC25912B6C430529F6A7F449FD96536DE269D1A1B015A4AC6B6E46EE19DCE8143726A6503E290E4BAE6BD78319B5878981F6CFFDB3B818209341FD68B]    m = libnum.s2n(flag)    c = str(pow(m, pub_key[1], pub_key[0]))  # 極長的一串東西    store = []    cipher = [3532577106, 1472742623, 3642468664, 4193500461, 2398676029, 617653972, 1474514999, 1471783658, 1012864704,              3615627536, 993855884, 438456717, 3358938551, 3906991208, 198959101, 3317190635, 3656923078, 613157871,              2398768861, 97286225, 2336972940, 1471645170, 3233163154, 583597118, 2863776301, 3183067750, 1384330715,              2929694742, 3522431804, 2181488067, 3303062236, 3825712422, 145643141, 2148976293, 2940910035, 506798154,              994590281, 2231904779, 3389770074, 2814269052, 1105937096, 1789727804, 3757028753, 2469686072, 1162286478,              680814033, 2934024098, 2162521262, 4048876895, 2121620700, 4240287315, 2391811140, 3396611602, 3091349617,              3031523010, 2486958601, 3164065171, 1285603712, 798920280, 2337813135, 4186055520, 3523024366, 1077514121,              1436444106, 2731983230, 1507202797, 500756149, 198754565, 2382448647, 880454148, 1970517398, 3217485349,              1161840191, 560498076, 1782600856, 2643721918, 1285196205, 788797746, 1195724574, 4061612551, 103427523,              2502688387, 4147162188, 617564657, 978211984, 1781482121, 2205798970, 3939973102, 3826603515, 659557668,              2582884932, 1561884856, 2217488804, 1189296962, 169145316, 2781742156, 1323893433, 824667876, 408202876,              3759637634, 4094868412, 1508996065, 162419237, 3732146944, 3083560189, 3955940127, 2393776934, 2470191468,              3620861513, 481927014, 2756226070, 3154651143, 1261069441, 2063238535, 2222237213, 101459755, 3159774417,              1721190841, 1078395785, 176506553, 3552913423, 1566142515, 1938949000, 1499289517, 3315102456, 829714860,              3843359394, 952932374, 1283577465, 2045007203, 3957761944, 3767891405, 2917089623, 3296133521, 482297421,              1734231412, 3670478932, 2575334979, 2827842737, 3413631016, 1533519803, 4008428470, 3890643173, 272960248,              317508587, 3299937500, 2440520601, 27470488, 1666674386, 1737927609, 750987808, 2385923471, 2694339191,              562925334, 2206035395]
        i = 0    # rsa 生成的密文遍歷加密    while i < len(c):  # i<155        index = 0        for ii in c[i:i + 4]:            index = (index << 8) + ord(ii)        store.append(index)
            i += 4        if not i < len(c):            key = [54, 54, 54, 54]            store_len = len(store)            res = encrypt(store_len, store, key)            if store == cipher:                print('You are right!')                input('')                quit()            else:                print('Why not drink a cup of tea and have a rest?')
            continue
    

    發現從cup包導入了一個encrypt函數。

    以下是對經key加密后的cup.pyc.encrypted的解密腳本

    [原創]Python逆向——Pyinstaller逆向-軟件逆向-看雪論壇-安全社區|安全招聘|bbs.pediy.com

    https://bbs.pediy.com/thread-271253.htm

          #!/usr/bin/env python3import tinyaesimport zlib
    CRYPT_BLOCK_SIZE = 16
    # 從crypt_key.pyc獲取key,也可自行反編譯獲取key = bytes('0000000000000tea', 'utf-8')
    inf = open('cup.pyc.encrypted', 'rb') # 打開加密文件outf = open('output.pyc', 'wb') # 輸出文件
    # 按加密塊大小進行讀取iv = inf.read(CRYPT_BLOCK_SIZE)
    cipher = tinyaes.AES(key, iv)
    # 解密plaintext = zlib.decompress(cipher.CTR_xcrypt_buffer(inf.read()))
    # 補pyc頭(最后自己補也行)outf.write(b'\x6f\x0d\x0d\x0a\0\0\0\0\0\0\0\0\0\0\0\0')
    # 寫入解密數據outf.write(plaintext)
    inf.close()outf.close()
    

    解密得到發現是一個python實現的xxtea加密,最基礎的版本,甚至連key都沒變。

    python實現xxtea加解密參考鏈接

    https://www.icode9.com/content-1-1126418.html

    #!/usr/bin/env python# visit https://tool.lu/pyc/ for more informationimport libnumfrom ctypes import *
    def MX(z, y, total, key, p, e):    temp1 = (z.value >> 5 ^ y.value << 2) + (y.value >> 3 ^ z.value << 4)    temp2 = (total.value ^ y.value) + (key[p & 3 ^ e.value] ^ z.value)    return c_uint32(temp1 ^ temp2)
    def encrypt(?, ?, ?):    ? = 0x9E3779B9L    ? = 6 + 52 // ?    total = c_uint32(0)    ? = c_uint32(?[? - 1])    ? = c_uint32(0)    if ? > 0:        total.value += ?        ?.value = total.value >> 2 & 3        ? = c_uint32(?[0])        ?[? - 1] = c_uint32(?[? - 1] + MX(?, ?, total, ?, ? - 1, ?).value).value        ?.value = ?[? - 1]        ? -= 1        if not ? > 0:            return ?
    

    先解密xxtea得到結果rsa加密的密文c。

    from ctypes import *
    def MX(z, y, total, key, p, e):    temp1 = (z.value>>5 ^ y.value<<2) + (y.value>>3 ^ z.value<<4)    temp2 = (total.value ^ y.value) + (key[(p&3) ^ e.value] ^ z.value)
        return c_uint32(temp1 ^ temp2)
    def encrypt(n, v, key):    delta = 0x9e3779b9    rounds = 6 + 52//n
        total = c_uint32(0)    z = c_uint32(v[n-1])    e = c_uint32(0)
        while rounds > 0:        total.value += delta         e.value = (total.value >> 2) & 3        for p in range(n-1):            y = c_uint32(v[p+1])            v[p] = c_uint32(v[p] + MX(z,y,total,key,p,e).value).value            z.value = v[p]        y = c_uint32(v[0])        v[n-1] = c_uint32(v[n-1] + MX(z,y,total,key,n-1,e).value).value        z.value = v[n-1]        rounds -= 1
        return v
    def decrypt(n, v, key):    delta = 0x9E3779B9    rounds = 6 + 52//n
        total = c_uint32(rounds * delta)    y = c_uint32(v[0])    e = c_uint32(0)
        while rounds > 0:        e.value = (total.value >> 2) & 3        for p in range(n-1, 0, -1):            z = c_uint32(v[p-1])            v[p] = c_uint32((v[p] - MX(z,y,total,key,p,e).value)).value            y.value = v[p]        z = c_uint32(v[n-1])         v[0] = c_uint32(v[0] - MX(z,y,total,key,0,e).value).value        y.value = v[0]         total.value -= delta        rounds -= 1
        return v
    #  test if __name__ == "__main__":    # 該算法中每次可加密不只64bit的數據,并且加密的輪數由加密數據長度決定
        k = [54, 54, 54, 54]    n = 155
        res=[3532577106, 1472742623, 3642468664, 4193500461, 2398676029, 617653972, 1474514999, 1471783658, 1012864704, 3615627536, 993855884, 438456717, 3358938551, 3906991208, 198959101, 3317190635, 3656923078, 613157871, 2398768861, 97286225, 2336972940, 1471645170, 3233163154, 583597118, 2863776301, 3183067750, 1384330715, 2929694742, 3522431804, 2181488067, 3303062236, 3825712422, 145643141, 2148976293, 2940910035, 506798154, 994590281, 2231904779, 3389770074, 2814269052, 1105937096, 1789727804, 3757028753, 2469686072, 1162286478, 680814033, 2934024098, 2162521262, 4048876895, 2121620700, 4240287315, 2391811140, 3396611602, 3091349617, 3031523010, 2486958601, 3164065171, 1285603712, 798920280, 2337813135, 4186055520, 3523024366, 1077514121, 1436444106, 2731983230, 1507202797, 500756149, 198754565, 2382448647, 880454148, 1970517398, 3217485349, 1161840191, 560498076, 1782600856, 2643721918, 1285196205, 788797746, 1195724574, 4061612551, 103427523, 2502688387, 4147162188, 617564657, 978211984, 1781482121, 2205798970, 3939973102, 3826603515, 659557668, 2582884932, 1561884856, 2217488804, 1189296962, 169145316, 2781742156, 1323893433, 824667876, 408202876, 3759637634, 4094868412, 1508996065, 162419237, 3732146944, 3083560189, 3955940127, 2393776934, 2470191468, 3620861513, 481927014, 2756226070, 3154651143, 1261069441, 2063238535, 2222237213, 101459755, 3159774417, 1721190841, 1078395785, 176506553, 3552913423, 1566142515, 1938949000, 1499289517, 3315102456, 829714860, 3843359394, 952932374, 1283577465, 2045007203, 3957761944, 3767891405, 2917089623, 3296133521, 482297421, 1734231412, 3670478932, 2575334979, 2827842737, 3413631016, 1533519803, 4008428470, 3890643173, 272960248, 317508587, 3299937500, 2440520601, 27470488, 1666674386, 1737927609, 750987808, 2385923471, 2694339191, 562925334, 2206035395]
        res = decrypt(n, res, k)
        # print(res)    for i in res:        print(chr(i>>24),end="")        print(chr((i&0x00ff0000)>>16),end="")        print(chr((i&0x0000ff00)>>8),end="")        print(chr(i&0x000000ff),end="")
     #c= 10610336534759505889607399322387179316771488492347274741918862678692508953185876570981227584004676580623553664818853686933004290078153620168054665086468417541382824708104480882577200529822968531743002301934310349005341104696887943182074473298650903541494918266823037984054778903666406545980557074219162536057146090758158128189406073809226361445046225524917089434897957301396534515964547462425719205819342172669899546965221084098690893672595962129879041507903210851706793788311452973769358455761907303633956322972510500253009083922781934406731633755418753858930476576720874219359466503538931371444470303193503733920039
    

    接下來是一個低解密指數 rsa 就可以得到flag了。

    import gmpy2from Crypto.PublicKey import RSAimport ContinuedFractions, Arithmeticfrom Crypto.Util.number import long_to_bytes
    def wiener_hack(e, n):    # firstly git clone https://github.com/pablocelayes/rsa-wiener-attack.git !    frac = ContinuedFractions.rational_to_contfrac(e, n)    convergents = ContinuedFractions.convergents_from_contfrac(frac)    for (k, d) in convergents:        if k != 0 and (e * d - 1) % k == 0:            phi = (e * d - 1) // k            s = n - phi + 1            discr = s * s - 4 * n            if (discr >= 0):                t = Arithmetic.is_perfect_square(discr)                if t != -1 and (s + t) % 2 == 0:                    return d    return False
    def main():    pub_key = [    0x649EE967E7916A825CC9FD3320BEABF263BEAC68C080F52824A0F521EDB6B78577EC52BF1C9E78F4BB71192F9A23F1A17AA76E5979E4D953329D3CA65FB4A71DA57412B59DFD6AEDF0191C5555D3E5F582B81B5E6B23163E9889204A81AFFDF119FE25C92F4ED59BD3285BCD7AAE14824240D2E33C5A97848F4EB7AAC203DE6330D2B4D8FF61691544FBECD120F99A157B3D2F58FA51B2887A9D06CA383C44D071314A12B17928B96F03A06E959A5AFEFA0183664F52CD32B9FC72A04B45913FCB2D5D2D3A415A14F611CF1EAC2D6C785142A8E9CC41B67A6CD85001B06EDB8CA767D367E56E0AE651491BF8A8C17A38A1835DB9E4A9292B1D86D5776C98CC25,    0x647327833ACFEF1F9C83E74E171FC300FA347D4A6769476C33DA82C95120ACB38B62B33D429206FE6E9BB0BB7AB748A1036971BEA36EC47130B749C1C9FF6FE03D0F7D9FC5346EB0E575BDFA6C530AA57CD676894FC080D2DD049AB59625F4B9C78BCFD95CDCD2793E440E26E189D251121CB6EB177FEDB596409034E8B0C5BBD9BD9342235DBB226C9170EFE347FF0FD2CFF9A1F7B647CC83E4D8F005FD7125A89251C768AFE70BDD54B88116814D5030F499BCAC4673CCCC342FB4B6AC58EA5A64546DC25912B6C430529F6A7F449FD96536DE269D1A1B015A4AC6B6E46EE19DCE8143726A6503E290E4BAE6BD78319B5878981F6CFFDB3B818209341FD68B]    # 0->n,1->e
        n = pub_key[0]    e = pub_key[1]    c = 10610336534759505889607399322387179316771488492347274741918862678692508953185876570981227584004676580623553664818853686933004290078153620168054665086468417541382824708104480882577200529822968531743002301934310349005341104696887943182074473298650903541494918266823037984054778903666406545980557074219162536057146090758158128189406073809226361445046225524917089434897957301396534515964547462425719205819342172669899546965221084098690893672595962129879041507903210851706793788311452973769358455761907303633956322972510500253009083922781934406731633755418753858930476576720874219359466503538931371444470303193503733920039    d = wiener_hack(e, n)    m = pow(c, d, n)    print(long_to_bytes(m)) #  flag{You_Need_Some_Tea}
    if __name__ == "__main__":    main()
    

    FakePica

    先用BlackDex脫個殼,然后把解密后的dex文件pull到自己的電腦上后拖進jadx。

    看到主要是一個登錄邏輯:

     

    題目邏輯非常簡單,可以直接Aes解密,但由于主類里有了解密的方法,肯定是要選擇更加有意思的方法來玩玩,我這里的做法是直接采用frida來hook。

    先hook繞過認證:

    console.log("Script loaded successfully");Java.perform(function x(){    console.log("inside java perform function");    //定位類    var my_class = Java.use("com.pica.picapica.MainActivity");    console.log("Java.use Successfully");    my_class.check.implementation = function(x,y){        return true;    }})
    

    返回頁面如下:

    看到有兩個解密相關的方法,果斷繼續hook。

    console.log("Script loaded successfully");Java.perform(function x(){    console.log("inside java perform function");    //定位類    var my_class = Java.use("com.pica.picapica.MainActivity");    console.log("Java.use Successfully");    my_class.check.implementation = function(x,y){        var email=this.decryptByHexString(this.bytesConvertHexString(this.content0.value),this.key.value);        var password=this.decryptByHexString(this.bytesConvertHexString(this.content1.value),this.key.value);        console.log("flag{"+email+password+"}");         return true;    }})
    

    直接拿到flag。

    奇怪的交易這題附件過大,這里就直接貼我的鏈接了:

    奇怪的交易

    python函數dword
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    之后想到了更完美的辦法
    高版本go語言符號還原
    x64dbg插件編寫基礎
    2023-04-13 09:28:19
    ② 腳本DLL,就是編寫一個DLL導出 AsyncStart() or Start(),然后通過命令scriptdll/dllscript來加載DLL執行代碼。在x64dbg的文檔中并沒有說明 "插件" 到底是一個什么東西,只是說插件的后綴名叫dp32或者dp64,通過觀察其他的插件發現其實就是DLL,只不過是導出了一些指定函數的DLL。本文的目的就是說明編寫x64dbg插件的步驟,然后編寫一個簡單的x64dbg插件。
    看程序圖標是個mfc的程序,先打開看看,隨便輸入一點東西,看到彈窗彈出:直接拖進ida搜索Wrong!!!字符串,借此通過查看引用跳轉到主函數
    比賽的時候由于各種原因沒有做出來,由于這道題需要unicorn的知識,對我本身而言是一個很好的學習機會,所以賽后進行了復現。
    在工作中,多多少少會遇到花指令的情況,本系列文章我會慢慢更新,把我學習過程分享給大家,從簡單的構造到如何結合手頭的工具patch。這里為什么沒有研究x86,第一因為我不會第二個原因是x86是非定長指令集,這會導致x86有那種雙字節的花指令不適合線形掃描,要校驗的太多了無法通過定長4字節的方式進行線性掃描。第一章簡單的花指令構造與修正◆example1 _main:
    0X01起源在攻防演練中通過運行惡意代碼連接C2是最常用的手段,但是由于對抗程度的提升。以360、天擎為代表的殺毒軟件針對信任鏈的檢測,已經變得愈來愈成熟。這里我們可以理解為,攻擊者通過利用"白加黑"這種攻擊方法。當攻擊者通過社工釣魚的手段,使得目標下載惡意的文件到目標自己的計算機上,并點擊運行白文件時,該文件會在運行時執行惡意DLL。
    奇安信的報告《使用和海蓮花相似混淆手法的攻擊樣本分析》[1]中分析了一個和APT32使用相同混淆方法的樣本。本文根據奇安信的報告以及報告中提到的參考文章和代碼[2]對該樣本進行去混淆。
    源碼分析1、LLVM編譯器簡介LLVM 命名最早源自于底層虛擬機的縮寫,由于命名帶來的混亂,LLVM就是該項目的全稱。LLVM 核心庫提供了與編譯器相關的支持,可以作為多種語言編譯器的后臺來使用。自那時以來,已經成長為LLVM的主干項目,由不同的子項目組成,其中許多是正在生產中使用的各種 商業和開源的項目,以及被廣泛用于學術研究。
    UAF漏洞全稱為use after free,即釋放后重用。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类