逆向攻防世界CTF系列34-BABYRE

参考xctf攻防世界 REVERSE 高手进阶区 BABYRE-CSDN博客

查完壳扔进IDA

image-20241116110727474

judge应该是个函数,点进去却是个数组??看了wp才知道这是smc自解密,再7-11行进行了加密

self-Modifying Code

在真正执行某一段代码时,程序会对自身的该段代码进行自修改,只有在修改后的代码才是可汇编, 可执行的

在程序未对该段代码进行修改之前,在静态分析状态下,均是不可读的字节码,IDA之类的反汇编器无法识别程序的正常逻辑。

SMC是一种局部代码加密技术,它可以将一个可执行文件的指定区段进行加密,使得黑客无法直接分析区段内的代码,从而增加恶意代码分析难度和降低恶意攻击成功的可能性。

SMC的基本原理是在编译可执行文件时,将需要加密的代码区段(例如函数、代码块等)单独编译成一个section(段),并将其标记为可读、可写、不可执行(readable, writable, non-executable),然后通过某种方式在程序运行时将这个section解密为可执行代码,并将其标记为可读、可执行、不可写(readable, executable, non-writable)。这样,攻击者就无法在内存中找到加密的代码,从而无法直接执行或修改加密的代码。

方法一:按第7-11行的逻辑逆向patch程序,再静态生成伪代码。Patch脚本如下: 注意此脚本只能运行一次

start_addr = 0x0000000000600B00

for i in range(182):
    ida_bytes.patch_byte(start_addr + i,idc.get_wide_byte(start_addr + i) ^ 0xC)

print('OK')

一开始这里也卡了我好一会,后来发现是我用了新版的IDA8.3,这里本来有个指针分析错误,IDA8.3直接把它当成数据去了,如果我用C(汇编),P(创建函数),在judge开头出按一下照样显示指针分析错误:(ps:不按C的话有时IDA会报错函数在指定地址具有未定义的指令/数据。您的请求已放入自动分析队列。按一下C可能是提醒它可以转成数据吧)

image-20241116122438290

点击run会增加一大段代码,如图:

image-20241116122547430

我们需要将上述红底色的代码,按U键(取消原来的定义)),再按 C(重新生成汇编代码),选中
600B00-600BB5(judge 的起止位置)按 P(重新生成 function)。这时就可以按 F5 生成 judge 的伪代码了。 代码如下:

这里原作者没说清楚对哪uc,实际上要对整个部分,红框里和红框上的都进行uc

__int64 __fastcall judge(__int64 a1)
{
  char v2[5]; // [rsp+8h] [rbp-20h] BYREF
  char v3[9]; // [rsp+Dh] [rbp-1Bh] BYREF
  int i; // [rsp+24h] [rbp-4h]

  qmemcpy(v2, "fmcd", 4);
  v2[4] = '\x7F';
  qmemcpy(v3, "k7d;V`;np", sizeof(v3));
  for ( i = 0; i <= 13; ++i )
    *(_BYTE *)(i + a1) ^= i;
  for ( i = 0; i <= 13; ++i )
  {
    if ( *(_BYTE *)(i + a1) != v2[i] )
      return 0LL;
  }
  return 1LL;
}

v2v3是连着的,它们应该可以理解为一个地址相同的数组,反编译给他编译成了两个变量

image-20241116123023750

写解密代码:

key="fmcd\x7Fk7d;V`;np"
# 或者key  = [102,  109,  99,  100,  127,  107,  55,  100,  59,  86,  96,  59,  110,  112]

flag=""
for i in range(14):
    flag+=chr(ord(key[i])^i)
print(flag)

flag{n1c3_j0b}

方法二:动态调试

linux动态调试

image-20241116124314449

跟踪judge然后cp

在 IDA 7.0 以后的版本中,要将:
idc.PatchByte() 改为 ida_bytes.patch_byte()
idc.Byte() 改为 idc.get_wide_byte()

python不会\x7F判断成4个字符