XNUCA2020-re

unravelmfc

(主要是学弟出的,我就打个下手
flag长度66(输入66长度字符才能点击确定)点确定没反应,只有flag正确才会弹框
首先使用下面的mfc的sig文件:
http://s.wjk.moe/bt/tmp/unravelmfc/afx140d.sig
在CCmdTarget::OnCmdMsg函数内部, 调用_AfxDispatchCmdMsg的call指令下断点,再点确定,即可在栈参数中找到对应的处理函数指针
MFC逆向
0x00CB1080 点确定后的处理函数 (程序基址我rebase到了0x00b10000)
00CB127C 是flag正确

直接看最下面的if,里面调用的两个函数。前33字符和后33字符分开判断检测。

if ( (unsigned __int8)j_check1((int)v14, v13) && (unsigned __int8)j_check2((int)v14 + v13, v13) )

前33字节首先RC4,再base64

flag{dsdafasdfasdsddddddddddddddddddddddddddddddddddddddddddddddd}
异或后:
00ACE9F4  26 44 D7 3B A8 E0 2F 7E 81 7E 9C 4C 39 A8 97 C8  &D×;¨à/~.~.L9¨.È  
00ACEA04  59 35 27 E6 1E CD 38 87 80 2C 99 C1 DD 5D 1F B0  Y5'æ.Í8..,.ÁÝ].°  
00ACEA14  9A 00 

base64是改了字符表的,在一个rc4加密的代码段里,x64dbg里将内存dump出来放到ida里用f5还勉强能看吧

enc_real = "B=.NI;&3JBZ;$;?(I72'0&4GLZDS2V6&%AF.!5#+J[F^"
import base64
def decoder(local_base64):
    import string
    real_base64_charset = string.ascii_uppercase + string.ascii_lowercase + string.digits + '+/'
    tmp_charset = "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab"
    b64_str = ''
    for i in local_base64:
        t = real_base64_charset[tmp_charset.find(i)]
        b64_str += t
    return (base64.decodebytes(b64_str.encode()))

def test1():
    orig = b"&D\xd7;\xa8\xe0/~\x81~\x9cL9\xa8\x97\xc8Y5'\xe6\x1e\xcd8\x87\x80,\x99\xc1\xdd]\x1f\xb0\x9a"
    encoded = ",G6:1]FC.Z]$BLT/1=E:U(GX,a;AV6E*C%U<S@X@*^%="
    assert decoder(encoded) == orig

test1()

def derc4(inp):
    moder_b =b'@(\xb6\\\xd3\x84\\\x1a\xe0\x18\xfd?]\xce\xf6\xbb=FC\x82z\xa9\\\xe3\xe4H\xfd\xa5\xb99{\xd4\xfe'
    res = []
    for i,j in zip(inp, moder_b):
        res.append(i^j)
    return bytes(res)

def test2():
    orig = b'flag{dsdafasdfasdsddddddddddddddd'

    out = b"\x26\x44\xD7\x3B\xA8\xE0\x2F\x7E\x81\x7E\x9C\x4C\x39\xA8\x97\xC8\x59\x35\x27\xE6\x1E\xCD\x38\x87\x80\x2C\x99\xC1\xDD\x5D\x1F\xB0\x9A"

    assert derc4(out) == orig

test2()

前半部分flag就出来了。。。

后33字符:第一个字符是f,后面三十二个字符单独加密
是tea算法,只改了delta。
需要解一个方程解出来是[0x2d46347f5e79f6f4, 0xDF3634AE2F9970FF, 0x6cacebd512c2fc6d, 0xe8e95dc6c558d3ec]

import ctypes
def encipher(v, k):
    y, z = [ctypes.c_uint32(x)
            for x in v]
    sum = ctypes.c_uint32(0)
    # delta = 0x9E3779B9
    delta = 0x2433b95a

    for n in range(32, 0, -1):
        sum.value += delta
        # z -- v8
        # y -- v6
        # 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]
        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]
    # print(hex(sum.value))
    return [y.value, z.value]


def decipher(v, k):
    y, z = [ctypes.c_uint32(x)
            for x in v]
    # sum = ctypes.c_uint32(0xC6EF3720)
    sum = ctypes.c_uint32(0x86772b40)
    # delta = 0x9E3779B9
    delta = 0x2433b95a

    for n in range(32, 0, -1):
        z.value -= (y.value << 4) + k[2] ^ y.value + sum.value ^ (y.value >> 5) + k[3]
        y.value -= (z.value << 4) + k[0] ^ z.value + sum.value ^ (z.value >> 5) + k[1]
        sum.value -= delta

    return [y.value, z.value]

keys = [3647016194, 716023165, 2742368241, 3265149203, 3583257832, 1619840614, 1834562594, 568710898, 3980038709, 2645385924, 945185819, 1912036253, 3705592552, 3939684768, 3133470052, 3662115500]

vv = [0x5e79f6f4, 0x2d46347f, 0x2F9970FF, 0xDF3634AE , 0x12c2fc6d, 0x6cacebd5, 0xc558d3ec, 0xe8e95dc6]

data = []
for i in range(4):
    v = vv[2*i: 2*(i+1)]
    v = v[::-1]
    k = keys[4*i:4*(i+1)]
    enc = decipher(v, k)
    data.append(enc[0])
    data.append(enc[1])

flag = ""
for d in data:
    flag = flag + (hex(d).replace("0x", "")[:-1]).decode('hex')[::-1]
print('f'+flag)

hellowasm

需要用node起一下直接点开不行

npm install http-server -g
http-server -p 8080

长度是42
这里可以直接用浏览器调试,还比较方便。
然后做了个base64, 每四个字符一组,异或[0xa, 0xb, 0xc, 0xd]
最后check的部分是个vm,算法是简单异或。
一点点分析的过程,分析了一点以后直接在异或和比较的函数下了断点发现算法其实比较简单。

+4; -> IP
+32 -> source
+16 -> str_index
+8 -> source[str_index]
+24 -> 

初始IP: 2128
202 -> IP + 5
203 -> IP + 5
204 -> IP + 1, load source
207 -> ^ +12  save in 12, IP + 1
201 -> next IP, save in 8, IP + 5

opcode
2128: 202
2129: 0
2130: 0
2131: 0
2132: 0
2133: 203
2134: 0
2135: 0
2136: 0
2137: 0
2138: 204
2139: 207
2140: 201
2141: 238
2142: 0
2143: 0
2144: 0
2145: 207 -> // source[0] ^ 238
2146: 209 -> 2160[index] == source[0] ^ 238
import base64
result = {2160: 190, 2161: 54, 2162: 172, 2163: 39, 2164: 153, 2165: 79, 2166: 222, 2167: 68, 2168: 238, 2169: 95, 2170: 218, 2171: 11, 2172: 181, 2173: 23, 2174: 184, 2175: 104, 2176: 194, 2177: 78, 2178: 156, 2179: 74, 2180: 225, 2181: 67, 2182: 240, 2183: 34, 2184: 138, 2185: 59, 2186: 136, 2187: 91, 2188: 229, 2189: 84, 2190: 255, 2191: 104, 2192: 213, 2193: 103, 2194: 212, 2195: 6, 2196: 173, 2197: 11, 2198: 216, 2199: 80, 2200: 249, 2201: 88, 2202: 224, 2203: 111, 2204: 197, 2205: 74, 2206: 253, 2207: 47, 2208: 132, 2209: 54, 2210: 133, 2211: 82, 2212: 251, 2213: 115, 2214: 215, 2215: 13, 2216: 227}

flag = []
li = [0]
for k in result.keys():
    li.append(result[k])

for i in range(1, len(li)):
    flag.append(li[i-1] ^ li[i] ^ 238)
ti = [0xa, 0xb, 0xc, 0xd]
tar = ""
for i in range(0, len(flag)-4, 4):
    for j in range(4):
        tar = tar + chr(ti[j] ^ flag[i+j])
print(base64.decodestring(tar))

babyarm

主要验证部分在sub_114D8, xxtea稍微改了一点,一次加密了16轮...长度也是16

#include <stdio.h>  
#include <stdint.h>  
#define DELTA 0x9e3779b9  
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))  
  
void btea(uint32_t *v, int n, uint32_t const key[4])  
{  
    uint32_t y, z, sum;  
    unsigned p, rounds, e;  
    if (n > 1)            /* Coding Part */  
    {  
        rounds = 6 + 52/n;  
        sum = 0;  
        z = v[n-1];  
        do  
        {  
            sum += DELTA;  
            e = (sum >> 2) & 3;  
            for (p=0; p<n-1; p++)  
            {  
                y = v[p+1];  
                z = v[p] += MX;  
            }  
            y = v[0];  
            z = v[n-1] += MX;  
        }  
        while (--rounds);  
    }  
    else if (n < -1)      /* Decoding Part */  
    {  
        for(int i = 0; i < 16; i++)
        {
            n = 16;  
            rounds = 6 + 52/n;  
            sum = rounds*DELTA;  
            y = v[0];
            do  
            {  
                e = (sum >> 2) & 3;  
                for (p=n-1; p>0; p--)  
                {  
                    z = v[p-1];  
                    y = v[p] -= MX;  
                }  
                z = v[n-1];  
                y = v[0] -= MX;  
                sum -= DELTA;  
            }  
            while (--rounds);  
        }
    }  
}  
  
  
int main()  
{  
    uint32_t v[16]= {0xB061F013, 0xB3C8567E, 0x9952A3C7, 0x451C2D3F, 0x3EE32267, 0xE3E22B3E, 0x43E5A250, 0x59B28ED0, 0x0F8649DC, 0x9BF4D083, 0x8A578110, 0x8604EC4F, 0x2EB5A27F, 0x1217DDF3, 0x93C9B253, 0xDC7F8E43};  
    uint32_t const k[4]= {2,2,3,4};  
    int n= 16;
    // for(int i = 0; i < 16; i++)
    btea(v, -n, k);
    for(int i = 0; i < 16; i++)
        printf("\"%x\", ", v[i]);
    return 0;  
}

>>> s = ["67616c66", "6330447b", "37306261", "35346146", "36623241", "62376646", "41364541", "41624261", "64354635", "43336263", "43446639", "66613545", "34354665", "38434144", "30354138", "7d413339"]
>>> flag = ""
>>> for i in s:
...     flag = flag + i.decode('hex')[::-1]
...
>>> flag
'flag{D0cab07Fa45A2b6Ff7bAE6AaBbA5F5dcb3C9fDCE5afeF54DAC88A5093A}'
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 197,814评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,124评论 2 375
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 144,814评论 0 327
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,924评论 1 268
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,815评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,562评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,944评论 3 388
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,582评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,859评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,881评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,700评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,493评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,943评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,115评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,413评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,978评论 2 343
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,182评论 2 339