CTF逆向-[b01lers2020]little_engine-cpp基本函数用法和byte类型要点

CTF逆向-[b01lers2020]little_engine-cpp基本函数用法和byte类型要点

来源:https://buuoj.cn/

内容

附件:https://pan.baidu.com/s/1g6wnqkuqydzHHlXInmRCNQ?pwd=mjlu 提取码:mjlu

答案:pctf{th3_m0d3rn_st34m_3ng1n3_w45_1nv3nt3d_1n_1698_buT_th3_b3st_0n3_in_1940}

总体思路

发现主要流程三个函数,分别是输出一个欢迎语、要求用户输入、判断用户输入

欢迎语中会判断用户的输入是否是在0x7e以内的,即是否是ascii,不是的话则认为用户在pwn,报警并退出程序

用户输入中会将用户的输入逐项与 0x91+sum(index)异或

判断用户输入中是将用户的输入逐项与g_key判断是否相等

反向编写脚本,得到答案

详细步骤

  • 查看文件内容

    • image-20220508213013238
  • 查看main函数,发现三个主要函数,分别是输出一个欢迎语、要求用户输入、判断用户输入

    • image-20220508213054457
  • 进入f_banner,发现内部是要求用户输入一个字符。随便输入一个字符回车即可。

    • 如果 getc(stdin) - 33) > 93即 char > 126的时候就会输出 Hey now, what're you trying to pull over on me, conductor?,估计是可能防止用户pwn
  • 进入f_input发现是要求用户输入字符串,有个混淆流程,可不管。随后进入f_xor_with_0x91_series将所有用户的输入异或 0x91+sum(index)

    • image-20220508214514378
    • image-20220508214609530
    • 判断输入是否有\n,有的话就抛出异常。否则就会对输入进行转换,v_temp从0x91开始,每轮增加index,然后与当前字符异或
  • 注意v_temp是一个byte类型,需要判断是否有溢出,溢出的时候则恢复到0 v_temp %= 0xff

  • 进入f_check发现是先将g_key复制0x12C个(300个)字节到v_key qmemcpy(v_key, g_key, 0x12CuLL);qmemcpy和memcpy是等价的,定义如下

    • 以source指向的地址为起点,将连续的n个字节数据,复制到以destin指向的地址为起点的内存中。C/C++语言中的一个用于内存复制的函数,声明在 string.h 中(C++是 cstring)。

      void *memcpy(void *destin, void *source, unsigned n);
      // 目标地址,源地址,数据长度。
      
  • 然后设置 *(v_key_addr + 292) =* ( v_key[36] + 4),即将v_key_addr第292个字节设置为了 v_key的第292个字节的值,没有变化。(v_key是int64类型,一个数值等于4个字节)

  • 随后调用了一个没有操作任何数值的memcpy

    • qmemcpy(
          (void *)((unsigned __int64)(v_key_addr + 1) & 0xFFFFFFFFFFFFFFF8LL),
          (const void *)((char *)v_key - ((char *)v_key_addr - ((unsigned __int64)(v_key_addr + 1) & 0xFFFFFFFFFFFFFFF8LL))),
          8LL * (((unsigned int)v_key_addr - (((_DWORD)v_key_addr + 8) & 0xFFFFFFF8) + 300) >> 3));
      
  • 并开始逐个字符判断输入是否等于v_key

  • 动调到判断逐个字符的位置,双击v_key,按shift+e复制其数值,得到exp

  • import struct
    g_key = 'E1E6D04AF2C37EAAE6FC42B2F2B501B4EC7D3920EFC04E13C82F67AA95796BF5F2064179D835F9C88EDE8851AC4CF081E0F4EE14ADF125BD827C6230A5F8802B79852AF86E5AAECB183AA2D009C58C5D3D346BF93B724B0E4AC37153E1E907BBC11AE7078F1B7574B98E5D2EC2F6173B52EDD7BD5EE9766372E2EA8951D74F34DC39D55892D9D2D2AA69F1BF9076E19C390D0CB3400648DA27D51EB84A944C98C48A68A8975E64F9C058F702728D3B881814EC8F42700C0B9666228EF758012EC5DC4BC071F4DAE63D73887DE4911F759070D60CA7097CF25A4EA1090C513CBAA864382D8C0088E36FEA77907439AA56F1A86E80CA3D9E69A46948F20A2CF733170F5CF28AE52F55A59F8B655476E064EE9D9B2D9B5F727F3BD9DF0569F09FF0A38CE6CDEFB4BC44543EE344'
    g_key = bytearray.fromhex(g_key)
    split_count: int = 4
    g_key = [g_key[x*split_count]
             for x in range(int(len(g_key)/split_count))]
    
    print([struct.pack('<B', x) for x in g_key])
    xor_pointer = 0x91
    result = []
    for index, x in enumerate(g_key):
        result.append(x ^ xor_pointer)
        xor_pointer += index
        xor_pointer %= 0xff # 防止溢出
    
    print([struct.pack('<B', x) for x in result])
    result = [chr(x) for x in result]
    result = result[0:75]
    print(''.join(result)) # pctf{th3_m0d3rn_st34m_3ng1n3_w45_1nv3nt3d_1n_1698_buT_th3_b3st_0n3_in_1940}
    
    
  • 得到答案 pctf{th3_m0d3rn_st34m_3ng1n3_w45_1nv3nt3d_1n_1698_buT_th3_b3st_0n3_in_1940}

  • 需要注意的是

    • 因为v_key的类型是int64,所有split_count=4按每4个字节分割开来。
    • 在每次增加xor_pointer的时候需要判断是否溢出
    • struct.pack <B 转换成无符号的byte类型
  • 参考Python使用struct库的用法

其他文档

更多CTF逆向题通用性做法和常用工具下载参考该博文内容:CTF逆向Reverse题的玩法

相关逆向CTF题

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值