收获

  • OllyDBG 动态调试

  • 当 main 中没有与 flag 有关的信息时,寻找其他可能与 flag 相关的函数

  • C 语言获取数据 高位 和 低位 的方法#include<windows.h>

LOWORD      取 32 bits 低 16 bits
HIWORD      取 32 bits 高 16 bits
LOBYTE      取 16 bits 低 8 bits
HIBYTE      取 16 bits 高 8 bits

【BJDCTF】Easy


思路

在 main 函数中未发现与 flag 有关的信息

BJDCTF-Easy1.png

设置时间,并将时间分解为 tm 结构,赋值给 v5,但是 v5 也没有使用

查看字符串也没有与 flag 有关的信息

BJDCTF-Easy2.png

依次查看其他的函数,发现大部分函数都是调用系统函数或是没有什么实际用处的函数
只有 __ques 函数的内容看起来不是没用的函数,比较正常

BJDCTF-Easy3.png

同时,在 __ques 函数中,包含打印操作:

for ( j = 50; j >= 0; --j )
    {
      if ( v2[j] )
      {
        if ( v2[j] == 1 )
        {
          putchar(42);                          // '*'
          ++v7;
        }
      }
      else
      {
        putchar(32);                            // ' '
        ++v7;
      }
      if ( !(v7 % 5) )
        putchar(32);
    }
    result = putchar(10);                       // '\n'

程序会输出 '*'' ''\n' 三种字符,而且函数名 __ques 让人联想到 question,这个函数很可能与 flag 有关

完整的 __ques 函数:

BJDCTF-Easy4.png

将这个函数拷贝出来,在 CLion 中跑一遍

但是 LODWORDHIDWORD 两个函数总是报错,导入库 #incluede<windows.h>
或者自己定义:

#define LODWORD(l)           ((WORD)((DWORD_PTR)(l) & 0xffffffff))
#define HIDWORD(l)           ((WORD)((DWORD_PTR)(l) >> 32))

都会报错,实在没办法了

但是由于 LODWORD(l) 的作用就是取数据 l 的 低 32位,HIDWORD(l) 就是取数据 l 的 高 32位
尝试手动实现该功能,将:

LODWORD(v6) = v4[2 * i - 1];  
HIDWORD(v6) = v0;  

替换为:

v6 = v0 * pow(2, 32) + v4[2 * i - 1];

虽然能跑,但是有几个位置输出不全:

BJDCTF-Easy5.png

大致能看出该程序打印的是一些字符,大概率就是 flag 了

既然 flag 是由该程序输出,而 main 中却并没有调用该函数,因此才导致 main 函数的内容看起来和 flag 无关,因此只需要手动让该程序执行 __ques 函数就可以了

这里使用 OllyDBG 进行动态调试
首先在 IDA 中注意到函数 __ques 的起始地址:0x00401520

BJDCTF-Easy6.png

在 OllyDBG 中 ctrl + g 定位到该地址:

BJDCTF-Easy7.png

__ques 函数入口处 F2 下断点
将此位置设置为新 EIP,即让程序直接从这里开始执行

BJDCTF-Easy8.png

同样,在 IDA 中找到 __ques 函数的结束地址:0x00401723(在 retn 返回之前)

BJDCTF-Easy9.png

在 OllyDBG 中该地址处 F2 下断点,便于查看 __ques 函数的输出信息:

BJDCTF-Easy10.png

F9 运行程序:

BJDCTF-Easy11.png


结果

HACKIT4FUN

BJDCTF-Easy12.png