逆向攻防世界CTF系列58-serial-150

64位无壳

image-20241212112248105

想着是不是被加密了

查了资料发现这种代码和数据混合的就是花指令。对于第一个红框中jz short near ptr loc_4009F3+2无法执行加法指令,所以直接从loc_4009F3处反汇编,一个指令错了,后面空间全部错误。

动态调试,main随便下个断点,慢慢F8,结果ret了,再调试慢慢看,发现一个cmp,是长度校验,后面输入16位的字符串

image-20241212140242934

会到

image-20241212140322442

可能是第一位E

再调试,输入Esssssssssssssss

image-20241212141349427

可以到这,跟进rbp-200h和rbp-1F1h发现是输入得开头和结尾的字符,意思是加起来得是9Bh,那么最后一位得是9Bh-45h=56h

EssssssssssssssV

按照这个顺序一步步下去,不用每次都重新输入调试

只用在cmp时更改寄存器的值就行

image-20241212141808995

EZsssssssssssssV

得flag

EZ9dmq4c8g9G7bAV

当然花指令是可以去除的,因此有第二种方法

我们发现A45-A55中间是不被执行的,而且感觉出现了很多次,是否是花指令呢?

image-20241212142041351

按一下c看看

image-20241212142157280

代码混淆与反混淆(逆向工程)-CSDN博客

可以参考我的这篇文章,0e8h是call的 意思,花指令常见的形式

我们往下翻发现相同的花指令出现了很多次

image-20241212142719238

可以用IDAPython批量去除(nop)

import idc

def Dword(addr):
    return idc.get_wide_dword(addr)

def PatchByte(addr, value):
    idc.patch_byte(addr, value)

addr = 0x40099c  # 起始地址
for i in range(0x400cac - 0x40099c):  # 遍历范围
    if Dword(addr + i) == 0x05ebb866:  # 检测前4字节是否为 0x05ebb866
        if Dword(addr + i + 4) == 0xfa74c031:  # 检测接下来的4字节是否为 0xfa74c031
            for a in range(9):  # 替换9字节为 NOP
                PatchByte(addr + i + a, 0x90)
print('Done')

在开头main处按一下p

就可以F5了

image-20241212143833485