IDA技巧(88)字符操作数类型和栈字符串

admin 2024年12月19日17:43:04评论11 views字数 2983阅读9分56秒阅读模式

我们之前讨论过操作数表示,但今天我们将使用一种特定的表示法来找到隐藏在其中的彩蛋。

更具体地说,是这张截图:

IDA技巧(88)字符操作数类型和栈字符串

函数surprise调用了printf,但传递给它的参数似乎都是数字。printf()不是通常处理字符串吗?这是怎么回事?

数字和字符

如你所知,计算机实际上并不区分数字和字符——对它们来说,这些都只是一些位的集合。因此,这完全是解释表示的问题。例如,以下所有内容都由相同的位模式表示:

  1. 65(十进制数)
  2. 0x4141hH'41(十六进制数)
  3. 0101101o(八进制数)
  4. 1000001b0b1000001(二进制数)
  5. 'A'(ASCII字符)
  6. WM_COMPACTING(Win32 API常量)
  7. (以及许多其他变体)

字符操作数表示

事实上,截图中的列表已从默认设置修改,以使彩蛋不那么明显。以下是原始版本的文本:

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line.text:00401010 ; intsurprise(...).text:00401010 _surprise proc near ; CODE XREF: _main↑p.text:00401010.text:00401010 var_24= dword ptr -24h.text:00401010 var_20= dword ptr -20h.text:00401010 _Format= byte ptr -1Ch.text:00401010 var_18= dword ptr -18h.text:00401010 var_14= dword ptr -14h.text:00401010 var_10= dword ptr -10h.text:00401010 var_C= dword ptr -0Ch.text:00401010 var_8= dword ptr -8.text:00401010 var_4= dword ptr -4.text:00401010.text:00401010 sub esp, 24h.text:00401013 mov eax, ___security_cookie.text:00401018xor eax, esp.text:0040101A mov [esp+24h+var_4], eax.text:0040101E lea eax, [esp+24h+var_24].text:00401021 mov dword ptr [esp+24h+_Format], 70747468h.text:00401029 pusheax.text:0040102A lea eax, [esp+28h+_Format].text:0040102E mov [esp+28h+var_18], 2F2F3A73h.text:00401036 pusheax ; _Format.text:00401037 mov [esp+2Ch+var_14], 2D786568h.text:0040103F mov [esp+2Ch+var_10], 73796172h.text:00401047 mov [esp+2Ch+var_C], 6D6F632Eh.text:0040104F mov [esp+2Ch+var_8], 73252Fh.text:00401057 mov [esp+2Ch+var_24], 74736165h.text:0040105F mov [esp+2Ch+var_20], 7265h.text:00401067 call_printf.text:0040106C mov ecx, [esp+2Ch+var_4].text:00401070 add esp, 8.text:00401073xor ecx, esp; StackCookie.text:00401075xor eax, eax.text:00401077 call@__security_check_cookie@4__security_check_cookie(x).text:0040107C add esp, 24h.text:0040107F retn.text:0040107F _surprise endp

在十六进制中几乎立刻就能看出:“数字”实际上是ASCII文本的短片段。代码正在逐块在栈上构建字符串。通过将数字转换为字符操作数类型(快捷键R),可以更明确地表示这一点。

为了帮助你判断这种操作数类型是否有意义,IDA在上下文菜单中显示了预览:

IDA技巧(88)字符操作数类型和栈字符串

这样就很清楚“数字”实际上是一个文本片段。将所有“数字”转换为字符常量后,模式开始显现:

IDA技巧(88)字符操作数类型和栈字符串

由于x86处理器家族的小端内存组织,单个片段必须反向读取(即字符字面量'ptth'对应于字符串片段"http")。

反编译器和优化的字符串操作

现在几乎可以看出结果应该是什么,但实际上还有一种更简单的方法来发现它。

因为处理寄存器大小的短字符串的方法通常被编译器用来内联实现常见的C运行时函数,而不是调用库函数,反编译器使用启发式方法来检测这种代码模式,并再次将其显示为等效的函数调用。如果我们反编译这个函数,反编译器会重新组装字符串,并在伪代码中显示它们:

IDA技巧(88)字符操作数类型和栈字符串

栈字符串

恶意软件通常使用类似的方法在栈上逐块(通常是逐字符)构建字符串,因为这样完整的字符串不会出现在二进制文件中,无法通过简单搜索发现。感谢IDA为没有显式分配类型的操作数显示的自动注释,它们在反汇编中通常很明显:

IDA技巧(88)字符操作数类型和栈字符串

反编译器轻松恢复完整字符串:

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(linevoid __noreturn start(){char v0[36]; // [esp+0h] [ebp-28h] BYREF    qmemcpy(v0, "FLAG{STACK-STRINGS-ARE-BEST-STRINGS}", sizeof(v0));    [...]}

学习资源

立即关注【二进制磨剑】公众号

👉👉👉【IDA 技巧合集】👈👈👈
👉👉👉【Github 安全项目合集】👈👈👈
学习零基础学习 IDA 逆向
【课程完结!内容揭秘!】7 天打造 IDA 9.0 大师:从零基础到逆向精英
🔥🔥🔥 第二期 Android 内核逆向🔥🔥🔥🔥
【课程完结!内容揭秘】第 2 期-Android 逆向内核攻防

原文始发于微信公众号(二进制磨剑):IDA技巧(88)字符操作数类型和栈字符串

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年12月19日17:43:04
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   IDA技巧(88)字符操作数类型和栈字符串https://cn-sec.com/archives/3528960.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息