[ACTF新生赛2020]Splendid_MineCraft
解密字节码
反编译源码:
|
|
条件判断:
|
|
第一个判断是输入的flag的最后一个字符的地址-v11的起始地址是否等于26,应该就是需要flag的长度为26:
|
|

后面两个判断就是判断flag的格式为:ACTF{xxxx}
strtok,用_将字符串分隔开,v3取的是最左边的一段字符,ACTF{xxxx,注意v17是从第六个字符开始,取4个字符的长度,然后v18是从第10个字符开始,取两个字符,这样其实都可以推断出来整个flag的格式为ACTF{xxxxxx_xxxxxx_xxxxxx}
|
|
往下存在一个unk_4051D8:

发现把unk_4051D8当成函数执行:((int (__cdecl *)(int *))unk_4051D8)(&v17),说明上面的一大段数据应该是字节码,然后将v17当成参数传入该函数中,重新运行,输入ACTF{aaaaaa_bbbbbb_cccccc},用x32dbg动态跟:
第一个循环:

|
|
异或结果:

看到EIP,发现就是通过循环解密出后面需要执行的字节码:

第一部分解密
解密之后的push ebp才是真正的函数开始,该函数先是往内存写值,一个是3@1b;b,一个是Welcome:

往下对刚刚写入的字符串的进行循环异或,

|
|
6次循环后得到:yOu0y*

最后出循环,test eax, eax,说明eax是作为函数执行结果,

重新运行执行输入:
ACTF{abcdef_hijklm_opqrst}
处理完第一个strtok之后会得到一个字符串为:abcdefRvabcdef,中间的Rv是固定的

三次strtok处理完之后会得到这样的结果:

然后来到字节码部分,注意传进来的字符串为:abcdefRvabcdef

进来之后先对字节码进行解密,解谜之后从0x9F515C开始才是函数处理的开始,注意传入的参数由EDX指向:

随后生成3@1b;b和welcome,对这两个值进行异或再加上0x23,然后跟传入的字符串进行对比,不难发现预期值应该是两个相等的,往下走完循环拿完处理后的结果为yOu0y*

重新运行:

此时相等了,跳转不实现:

将edx作为计数器来存储相等的个数,最后对比是否全部相等,将返回值置为1:

第二部分解密
往下来到第二个部分的验证:

|
|

异或之后的值作为key,然后对:405018开始的值进行异或,跟第一个函数一样,通过这个key对字节码进行解密,然后再执行,这里的内容就是第二部分字符串的验证:


开局几个循环啥事都没干就是将输入的第二部分字符串进行memcpy,到这个位置才真正对字符串进行处理:

往下的mov很重要,EAX此时的值为0x705018,也就是该函数的字节码首地址,这里异或的结果作为数组下标,将字节码以byte的形式存储到EBX:

往下从0x705018+0x166取值与上面通过偏移拿到的值进行比较:

edi作为计数器,回到异或之前可以看到ecx的值来自于edi:



得到异或逻辑为:
|
|
exp:
|
|
byte_405018,用Ghidra的字节复制复制下来:
|
|

得到flag2:

第三部分解密
第三部分字符串发现就是直接进行strncmp:

可以得到第三部分的字符串为:5mcsM<,最终flag:
ACTF{yOu0y*_knowo3_5mcsM<}
Exp
|
|
