BUUCTF [NPUCTF2020]EzObfus-Chapter2

一.这道题应该就是正常情况下的一个难题了,没有强大的伪代码分析和写脚本的功底,这道题确实不太好写,我看网上有好多angr指令解出来的,虽然这也是种方法,但是我觉得还是用正常的方法写,自己才能进步的更快。

1.正常IDA打开:

主函数是比较正常的,flag一共有22位,第18-22行有个判断,我们可以知道a1的值,注意第12行sub_41644A函数,这个函数没有参数,点进去里面是个套娃,通过动态调试还有一次次的实验尝试,最终知道了是将输入的字符串每一个加“i”,然后再异或“i”。

2.第13-17行的运算过程也比较正常,直接正向写脚本爆破就可以,因为第16行的

 a1[i] = ((int)(unsigned __int8)a1[i] >> 3) | (32 * a1[i]);

这个逆向过程确实不太好写(反正我是不会逆着写。。),所以我们通过正向的过程,爆破一下输入的值,加上最后的判断,就能得到flag经过sub_41644A函数变换后的值,具体的python脚本:

a1 = [0x6E, 0x10, 0xEC, 0x13, 0xC1, 0xCB, 0xF0, 0x2D, 0xC6, 0x32, 
  0xFD, 0x86, 0xEE, 0xCB, 0x89, 0x92, 0x3C, 0x46, 0x49, 0x71, 
  0x62, 0x57]
dword_424080 = [0x21,0x3f,0xa3,0xe9,0x8f,0x00]
for j in range(1,len(a1)):
    for i in range(256):
        c = i
        c += (dword_424080[j % 6] >> 6) ^ (16 * dword_424080[(j - 1) % 6])
        c = ((c&0xff) >> 3) | (32 * (c&0xff))
        if (c&0xff) == a1[j]:
            print(chr(i),end='')

        #pue|nYD^]DwNZaOBJ{!

我们得到了经过变化的flag从第二位到最后一位的值,再根据动态调试,第一位输入什么就输出什么,所以根据最后一个判断,它的值是0x6E,也就是“n”。这时候,我们可以再写一个脚本,逆向还原出flag:

a = 'npue|nYD^]DwNZaOBJ{!'    #刚才得到的字符串前面加“n”
for i in range(len(a)):
    flag = ''
    flag += chr((ord(a[i])^i)-i)  #通过动调得到
    print(flag,end='')

    #npuctf{WDNMDo6F_OBFU!}

本来以为这肯定就是flag了,没想到还是我年轻了。。。

3.中间三位o6F感觉和flag关系不大,其中三位中的第一位应该是“_”,剩下两位直接爆破:

from itertools import *
import subprocess   #subprocess 模块允许你生成新的进程,连接它们的输入、输出、错误管道,并且获取它们的返回码
for i in range(1):
    for j in range(32,127):
        for k in range(32,127):
            flag ="npuctf{WDNMD_"+chr(j)+chr(k)+"_OBFU!}"
            p = subprocess.Popen([r"C:\Users\admin\Desktop\attachment.exe"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            p.stdin.write(flag.encode())
            p.stdin.close()
            out=p.stdout.read()
            p.stdout.close()
            if "E".encode() not in out:
                print(flag)
                exit()

这个爆破脚本浅显易懂,稍微复杂点的可能是subprocess这个模块,具体可以参考:https://docs.python.org/zh-cn/3/library/subprocess.html#using-the-subprocess-module

运行得到flag

npuctf{WDNMD_LJ_OBFU!}

像这个爆破脚本的话, 有的windows下的exe程序可以爆破出来,有的爆破不出来,这个我还正在研究,不过上述爆破脚本完全可以当成一个模板来使用,具体了解原理的大佬可以一起交流一下。

二.此外还有第二种,也就是angr指令的方式得到flag。

from angr import *

p = Project('C:\Users\admin\Desktop\attachment.exe',auto_load_libs = False)
state = p.factory.blank_state(addr=0x004164F8)
simfd = state.posix.get_fd(0)
data,real_size = simfd.read_data(22)
state.memory.store(0x0042612C,data)
state.memory.store(0x00426020,data)
sm = p.factory.simulation_manager(state)
sm.one_active.options.add(options.LAZY_SOLVES)
sm.explore(find = 0x00416609,avoid = 0x004165EA)
text = sm.one_found.solver.eval(sm.one_found.memory.load(0x0042612C,22),cast_to = bytes)
print (text)

这个脚本是参照别的大佬的wp,具体的angr原理可以参考:

https://xz.aliyun.com/t/3990

之后我会做angr指令专题详解,运行之后得到:

最终得到flag:

flag{WDNMD_LJ_OBFU!}

 

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>