当前位置: 首页 > news >正文

[CTF Reverse] 初见SMC

初见SMC——smc.exe

题目:

9e798da56338ce136760a03a91f948a5

  • 把附件smc.exe拖入IDA Pro 8.3定位main函数,反编译结果如下:
int __fastcall main(int argc, const char **argv, const char **envp)
{puts(Buffer);sub_140001140("%s", byte_140005678);sub_140001280();if ( (unsigned int)sub_1400011C0() )sub_140001070(aGoodUDoIt);elsesub_140001070(aSorryTryAgain);return 0;
}

容易看出,sub_7FF6AC891140("%s", byte_7FF6AC895678) 是一个请求输入的语句,输入后,byte_7FF6AC895678将存储我们的输入内容。if语句判断了sub_1400011C0()的结果,双击查看该函数。
屏幕截图 2025-08-03 132214
很杂乱,和之前训练的情况不同,这次我们从这里无法读取到有效信息。所以我们转换角度,去看看另一个函数sub_140001280()。

__int64 sub_140001280()
{int i; // [rsp+20h] [rbp-28h]unsigned int v2; // [rsp+24h] [rbp-24h]DWORD flOldProtect[2]; // [rsp+30h] [rbp-18h] BYREFflOldProtect[1] = -858993460;flOldProtect[0] = (unsigned int)malloc(8ui64);v2 = VirtualProtect((char *)sub_1400011C0 - (unsigned int)sub_1400011C0 % 0x1000, 0x1000ui64, 0x80u, flOldProtect);for ( i = 0; i < 190; ++i ){*((_BYTE *)sub_1400011C0 + i) ^= 0x66u;v2 = i + 1;}return v2;
}

我们注意到了VirtualProtect(),经过搜索,这是一个外部方法:

VirtualProtect函数是Windows API中的一个函数,
它用于更改调用进程的虚拟地址空间中已提交页面区域的保护。
这个函数允许开发者修改一个内存区域的保护属性,例如将一个内存区域设置为可执行,
这在某些情况下,如动态代码生成或自修改代码中非常有用。

结合题目简介,我们搜索What is SMC?结果是自定义代码混淆(Self-Modifying Code),代码有反编译处理,我们需要攻破它。
回到sub_1400011C0(),发现JUMPOUT语句后面的地址双击会跳到sub_140001280(),遂搜索JUMPOUT,发现相关博客介绍:【Android安全】IDA 处理伪代码JUMPOUT指令(Undefine + Create Function)
我们的思路已经明确:

  • 设置断点,让程序进行代码解密
  • 捕获解密后的汇编并且反编译
  • 分析代码,编写flag脚本

根据逆向工程基础之代码混淆/反混淆技术(1):SMC混淆原理分析出,sub_140001280()就是解密函数。回到main,在箭头位置打上断点

...sub_140001280();
-->  if ( (unsigned int)sub_1400011C0() 
...

F9进行调试,选择Local Windows Debugger。命令行弹出,随便输入点什么,然后回车屏幕截图 2025-08-03 134722
双击sub_7FF6A08911C0(),报错了。image
没关系,点OK。
image
到这里右键,选择Text View。
image
从最上面 .text:00007FF6A08911C0一直选到.text:00007FF6A089127E align 20h(文章最后会解释为什么这样选),按u来取消定义(Undefine),光标回到最上面.text:00007FF6A08911C0,按p重新编译,然后F5反编译。得到:

__int64 sub_7FF6A08911C0()
{int i; // [rsp+20h] [rbp-48h]unsigned int v2; // [rsp+24h] [rbp-44h]char Str[24]; // [rsp+30h] [rbp-38h] BYREFstrcpy(Str, "EOBDXZFP|V|GL|JW^");memset(&Str[18], 0, 2ui64);v2 = 1;for ( i = 0; i < strlen(Str); ++i ){if ( (Str[i] ^ 0x23) != byte_7FF6A0895678[i] )v2 = 0;}return v2;
}

这就是解密后得到的函数,不难看出flag就在这里。编写flag脚本。

Str = "EOBDXZFP|V|GL|JW^"
strarr = [ord(m) for m in Str]for i in range(len(strarr)):strarr[i] ^= 0x23flag = [chr(c) for c in strarr]
print(''.join(flag))

得到flag{yes_u_do_it}

成功!

为什么从.text:00007FF6A08911C0一直选到.text:00007FF6A089127E

解密函数sub_140001280()中的for循环运行了190次,修改了sub_1400011C0(),而190换成hex是BE,11C0+BE = 127E,所以选到127E。

2025 08 04
http://www.sczhlp.com/news/5214/

相关文章:

  • 深入指南:在SCSS中高效使用@font-face引入自定义字体
  • 题解:qoj9564 Hey, Have You Seen My Kangaroo?
  • BT137-800-ASEMI工业自动化BT137-800
  • 8.4
  • Java数组
  • appium安装文档
  • 正之和软件
  • Linux CentOS 系统中 X11(X Window System)​​ 的详细解析
  • 使用OpenAI文本转语音(Text to Speech)详解
  • 深入解析:jmeter--While控制器--循环直到接口响应符合条件
  • Git基本使用
  • 又是周一,又要上班
  • 杂交瘤细胞构建|单克隆抗体筛选|高效抗体制备
  • 生成式AI实现多模态信息检索新突破
  • 【自学嵌入式:51单片机】LCD1602
  • Java编程练习:洗牌
  • 猿大师中间件:Chrome网页内嵌Windows PC版微信桌面EXE应用程序
  • 实用指南:Cost-Effective and Scalable: A Smarter Choice for RISC-V Development
  • 洛谷题单指南-状态压缩动态规划-P1441 砝码称重
  • linux文件系统镜像导出位docker镜像
  • vue-element-admin 学习笔记
  • 通过Modbus RTU转Profinet网关实现SB150变频器与PLC的集成配置
  • 在 Ubuntu 上,通过 systemctl 来操作自己的程序
  • 2025国自然放榜在即时间预测!速看! | 附600+份国自然中标标书
  • 与过去告别2025
  • ClickHouse Windows迁移方案与测试 - 实践
  • 【OI学习笔记】AC自动机
  • 查看图片的时候它的背景有黑一块白一块的方块,但是发送出去它这些方块就不显示的原因
  • 国产化Word处理控件Spire.Doc教程:Python提取Word文档中的文本、图片、表格等
  • 【ACM出版,北京外国语大学主办】2025年人工智能与计算社会科学国际研讨会(AICSS 2025)