二进制安全面经汇总

C/C++逆向开发

C/C++结构体大小如何计算?
struct MyStruct {
    char a;     // 1 byte
    int b;      // 4 bytes
    short c;    // 2 bytes
};

这个结构体占用12字节,结构体成员需要内存对齐

C++的结构体和C的区别?

C++在继承C的 struct 功能的基础上,融入了面向对象的概念,使得 struct 比C语言中的结构体强大得多。在C++中,struct可以包含:

模板 (Templates): C++结构体可以使用模板,实现泛型编程。

成员变量 (Data Members): 与C相同,可以包含各种数据类型的成员。

成员函数 (Member Functions): 这是与C结构体最主要的区别。C++结构体可以包含函数,这些函数可以操作结构体的数据成员,实现了数据和行为的封装。

访问修饰符 (Access Specifiers): C++结构体支持 publicprivateprotected 等访问修饰符,用来控制结构体成员(变量和函数)的可访问性。

构造函数 (Constructors): 可以定义构造函数来初始化结构体对象。

析构函数 (Destructors): 可以定义析构函数来在对象生命周期结束时执行清理工作。

继承 (Inheritance): C++结构体可以像类一样继承其他结构体或类,并被其他结构体或类继承。

new和malloc的区别(delete和free的区别)

相同点

  • 都可用于内存的动态申请和释放

不同点

  • 前者是C++运算符,后者是C/C++语言标准库函数
  • new自动计算要分配的空间大小,malloc需要手工计算
  • new是类型安全的,malloc不是。例如:
int *p = new float[2]; //编译错误
int *p = (int*)malloc(2 * sizeof(double));//编译无错误
  • new调用名为operator new的标准库函数分配足够空间并调用相关对象的构造函数,delete对指针所指对象运行适当的析构函数;然后通过调用名为operator delete的标准库函数释放该对象所用内存。后者均没有相关调用
  • 后者需要库文件支持,前者不用
  • new是封装了malloc,直接free不会报错,但是这只是释放内存,而不会析构对象
如何找到main函数?(这里要继续细分,win32桌面程序,控制台程序,linux下的命令行程序)

构造函数与析构函数调用时机
  • 构造函数在对象创建时被调用,负责初始化对象的内部状态。
  • 析构函数在对象销毁时被调用,负责清理对象持有的资源。
  • 拷贝构造函数:使用一个已经创建完毕的对象来初始化一个新对象时,值传递的方式给函数参数传值时
C/C++编程有没有遇到的安全问题(我讲的一个浅构造导致的double free)
  • C/C++对象默认的拷贝行为是浅拷贝
  • 当对象包含指向动态分配内存的指针时,浅拷贝会导致多个对象拥有指向同一块内存的指针。
  • 如果这些对象都在各自的析构函数中尝试释放这块内存,就会发生双重释放 (Double Free) 。
  • 双重释放是一种严重的内存错误,可能导致堆损坏 (Heap Corruption) ,进而引发程序崩溃或被攻击者利用执行恶意代码。
重载如何实现
  • 静态函数名重载,动态虚函数重写。
  • 同名函数,参数不同形成静态函数重载,由编译器决定函数调用。
  • 子类虚继承父类时,子类中存在与父类中同名同参的函数形成动态函数重写,程序运行时根据虚函数表决定函数调用。
  • 子类直接继承父类时,子类中存在与父类中同名的函数形成函数隐藏,编译器只会使用子类中的同名函数,父类中的同名函数全部被隐藏。
虚函数如何实现?(重点,几乎必问,虚表指针位置)

虚继承/多重继承的内存结构(VC和G++中虚继承中虚表结构不太一样)

switch的实现与优化(难点)

try-catch的实现与优化(难点,会顺着问到windows异常处理机制)

三种循环哪种效率最高?

32位下函数调用约定有哪些?
  • __cdecl:参数从右到左依次压入栈中。由调用者负责清理栈空间。支持可变数量参数的函数 (如 printfscanf)。它是C和C++中自由函数的默认调用约定,使用场景: C标准库函数,带有可变参数的函数。
  • __stdcall:参数从右到左依次压入栈中。由被调用者负责清理栈空间。参数数量固定。由于被调用者清理栈,可以减小调用者处的代码量,适用于大量独立函数的调用。这是WinAPI函数的标准调用约定。
  • __fastcall:使用寄存器传递前几个参数,其余参数从右到左压入栈中。具体使用哪个寄存器根据编译器和参数类型而异(例如,在MSVC中,前两个 DWORD 或更小的参数通常使用 ECX 和 EDX 寄存器)。由被调用者负责清理栈空间(此处重点!与64位fastcall不同!)。
64位下函数调用约定?

除了少数使用可变参数的函数例如printf仍然使用__cdecl以外,其他全部统一为__fastcall。

前四个整数或指针参数(按从左到右的顺序)依次使用 RCX, RDX, R8, R9 寄存器传递。前四个浮点参数(按从左到右的顺序)依次使用 XMM0, XMM1, XMM2, XMM3 寄存器传递。剩下的参数按照从右到左的顺序压入栈中。复杂的结构体或对象通常会根据大小和特性,可能通过寄存器传递,或者通过在栈上分配空间,并将指针作为隐藏的第一个参数通过 RCX 传递来模拟按值传递。返回值通常通过 RAX或 XMM0寄存器返回。较大的结构体或对象返回值通常通过调用者在栈上分配空间,并将该空间的指针作为隐藏的第一个参数(通常在 RCX 之前,或者如果 RCX 被用于第一个参数,则用 RDX 等)传递给被调用函数,被调用函数将结果写入该空间。(传指针原理)

由调用者负责管理和清理为参数分配的栈空间。调用者在调用函数之前,必须在栈帧中为其参数分配至少 32字节 的空间。即使被调用函数不需要任何栈空间来存储寄存器参数,这32字节也必须预留。
这32字节(4个 8字节,对应前四个寄存器参数 RCX, RDX, R8, R9)被称为“影子空间”或“主页空间”。被调用者可以使用这块空间来保存传入的寄存器参数,这对于需要使用栈上的参数地址或在同一函数内调用其他函数时非常有用。

二进制逆向(反调试/脱壳/免杀/挂钩/注入)

32位程序如何在64位机器上运行?
  • 64位exe只能加载64位dll,32位exe只能加载32位dll。wow64目录当中存储了系统关键组件的特殊32位版本以便于32位程序调用,ntdll.dll,user32.dll等会调用wow64.dll,由wow64调用原生64位dll来实现相关功能,然后将相关返回转换为32位版本。
  • 文件系统重定向,注册表重定向,参见msdn。
  • 64位程序与32位程序必须使用进程间通信机制。
  •  WOW64 支持 4 GB 虚拟地址空间。
  • 主要开销来源于系统调用翻译 (Thunking) ,需要在32位和64位模式之间切换和转换参数。对于CPU密集型的C++计算代码,开销非常小,因为处理器直接执行32位指令。
PE格式(重点,几乎必问)
PE装载进内存执行的过程

内核首先创建一个新的进程对象和其对应的私有虚拟地址空间。每个进程都有自己独立的4GB(32位)或128TB(64位)虚拟地址空间。内存映射文件(延迟加载机制)。解析PE头和可选头。映射节区到虚拟地址空间。处理导入表。处理ASLR重定位。TLS回调函数的执行。执行C/C++运行时初始化代码。跳转到程序入口点执行。

知道哪些反调试手段?

PEB.BeingDebugged 、 PEB.NtGlobalFlag、PEB.processHeap、EPROCESS.flag.NoDebugInherit 、EPROCESS.InheritedFromUniqueProcessId 、EPROCESS.DebugPort。

枚举窗口,枚举调试器进程,调试权限打开winlogon进程。

TLS回调函数,调试器异常处理。

windbg基本命令

调试器原理(三大断点实现)
  • 软件断点INT 3(0xCC),当CPU执行到 INT 3 指令时,会触发一个中断(异常),操作系统捕获这个异常(EXCEPTION_BREAKPOINT),并通知调试器。实现过程: 调试器首先使用 ReadProcessMemory 读取目标地址处的原始指令字节,然后使用 WriteProcessMemory 将 0xCC写入该地址。当断点命中后,调试器收到通知,它会将 0xCC 替换回原始指令字节,然后通常会将指令指针(EIP/RIP)减去该指令的长度(通常为1字节,指向替换前的原始指令位置),最后恢复执行。下次继续执行时,原始指令会被执行。缺点:容易被检测0xCC。
  • 硬件断点DR0-DR3用于存储断点地址,硬件断点不修改代码或内存,更难被直接检测。但数量有限(通常只有4个),且只能用于特定的触发条件(执行、读、写、读写)。一些反调试技术会检查线程上下文中的DR寄存器状态。
  • 单步执行标志,x86处理器引入的PSW寄存器,有一个陷阱标志位,名为Trap Flag,简称TF。当TF为1时,CPU每执行一条指令便会产生一个调试异常,中断到调试异常处理程序。
  • 内存断点,调试器修改内存页的保护属性(例如,设置为 PAGE_NOACCESS 或 PAGE_GUARD),当目标程序访问该页面时触发访问违规异常(EXCEPTION_ACCESS_VIOLATION),调试器捕获该异常并处理。
如何脱壳(压缩壳/加密壳/虚拟化壳)

为什么脱完壳要修复导入表?

加壳程序先运行壳代码,壳代码负责在内存中解密/解压(脱壳)出原始程序代码。原始程序的导入表在加壳过程中被破坏或被壳隐藏,无法被系统加载器正确处理。脱壳后(原始代码在内存中),依赖动态链接的函数调用(如调用Windows API,C++标准库依赖的系统调用等)仍然需要通过导入表寻址,而此时导入表是错误的或缺失的。修复导入表是为了让脱壳后的原始程序代码能够找到并正确调用其依赖的外部函数,使其能够正常执行。

花指令有没有脱过?

有没有写过IDA脚本(逆向岗位几乎必问)

如果一个程序没有字符串/字符串被混淆了如何找核心代码?

分析 API 调用,交叉引用分析,动态调试

内存泄漏如何排除

有没有做过免杀,怎么做的?

沙箱有接触过吗?

有没有用过虚拟机?(QEMU, VMware Bochs)虚拟化有哪几种方式实现?虚拟机查杀有什么思路过吗?

Hook有哪些方法?

用户层的inline hook,iat hook,eat hook

如果inline hook前几个字节不能正好5字节Patch如何处理?

分析过哪些病毒样本?病毒分析有什么方法?

特征码怎么提取的?

flags寄存器有哪些位,有什么作用(OF, ZF, TF, 虚拟位)

状态标志

状态标志用于指示算术运算(例如使用ADDSUBMULDIV等指令)后的结果,它们包括包括有以下几个标志:

  • CF:进位标志(Carry flag)是标志寄存器的第0位,又被称之为CY,当其被设置时表示运算结果的最高有效位发生进位或借位的情况,并在无符号整数的运算中表示运算的溢出状态。
  • PF:奇偶校验标志(Parity flag)是标志寄存器的第2位,当其被设置表示结果中包含偶数个值为1的位,否则表示结果中包含奇数个值为1的位。
  • AF:辅助进位标志(Auxiliary carry flag)是标志寄存器的第4位,当其被设置表示在算术运算中低三位发生进位或借位(例如ALAH进位或借位)或BCD码算术运算中发生进位或借位的情况。
  • ZF:零标志(Zero flag)是标志寄存器的第6位,当其被设置时运算的结果是否等于0,否则不等于0。
  • SF:符号标志(Sign flag)是标志寄存器的第7位,当其被设置时表示结果为负数,否则为正数。
  • OF:溢出标志(Overflow flag)是标志寄存器的第11位,当其被设置时代表运算结果溢出,即结果超出了能表达的最大范围。

状态标志中,只有CF标志能被直接通过STCCLC以及CMC指令修改。

控制标志

  • DF:方向标志(Direction flag)是标志寄存器的第10位,用于指示串操作指令地址的变化方向。当其被设置时,存储器由自高向低方向变化,否则相反。STDCLD指令分别用于设置、清除DF标志的值。

系统标志

ID:ID标志(Identification flag)是标志寄存器的第21位,通过修改该位的值可以测试是否支持CPUID指令。

TF:陷阱标志(Trap flag)是标志寄存器的第8位,当其被设置时将开启单步调试模式。在其被设置的情况下,每个指令被执行后都将产生一个调试异常,以便于观察指令执行后的情况。

IF:中断标志(Interrupt flag)是标志寄存器的第9位,当其被设置时表示CPU可响应可屏蔽中断(maskable interrupt)。

IOPL:I/O特权级别标志(I/O privilege level flag)是标志寄存器的第12位以及第13位,表示当其程序或任务的I/O权限级别。I/O权限级别为0~3范围之间的值,通常一般用户程序I/O特权级别为0。当前运行程序的CPL(current privilege level)必须小于等于IOPL,否则将发生异常。

NT:嵌套任务(Nested task flag)是标志寄存器的第14位,用于控制中断返回指令IRET的执行方式。若被设置则将通过中断的方式执行返回,否则通过常规的堆栈的方式执行。在执行CALL指令、中断或异常处理时,处理器将会设置该标志。

RF:恢复标志(Resume flag)是标志寄存器的第16位,用于控制处理器对调试异常的响应。若其被设置则会暂时禁止断点指令产生的调试异常,其复位后断点指令将会产生异常。

VM:虚拟8086模式标志(Virtual 8086 mode flag)是标志寄存器的第17位,当其被设置表示启用虚拟8086模式(在保护模式下模拟实模式),否则退回到保护模式工作。

AC:对齐检查标志(Alignment check (or access control) flag)是标志寄存器的第18位。当该标志位被设置且CR0寄存器中的AM位被设置时,将对用户态下对内存引用进行对齐检查,在存在未对齐的操作数时产生异常。

VIF:虚拟中断标志(Virtual interrupt flag)是标志寄存器的第19位,为IF标志的虚拟映象。该标志与VIP标志一起,且在CR4寄存器中VMEPVI位被设置且IOPL小于3时,处理器才将识别该标志。

VIP:虚拟中断挂起标志(Virtual interrupt pending flag)是标志寄存器的第20位,其被设置表示有一个中断被挂起(等待处理),否则表示没有等待处理的中断。该标志通常与VIF标志搭配一起使用。

控制寄存器有哪些,有什么作用(可以重点说说CR0和CR3)

CR0:

PE (Protection Enabled – 保护模式启用标志):

位置: Bit 0

作用: 这是最重要的标志之一。当PE设置为1时,处理器进入保护模式。在保护模式下,处理器支持多任务、内存段保护、特权级(Ring 0-3)等高级功能。当PE设置为0时,处理器运行在实模式下(如早期DOS)。

与Windows和C++关联: Windows是一个运行在保护模式下的操作系统。所有的用户态C++程序(包括你平时写的应用程序)和内核态代码都运行在PE=1的环境下。保护模式提供了内存隔离和权限控制,这是现代操作系统安全的基础。没有保护模式,进程之间将无法隔离,任意程序都可以访问或修改任何内存区域,安全将无从谈起。

WP (Write Protect – 写保护标志):

位置: Bit 16

作用: 当WP设置为1时,如果CPL(Current Privilege Level,当前特权级)小于3(即在内核态Ring 0),试图写入用户态不可写的内存区域会引起写保护故障。这阻止了内核意外或恶意地修改用户态页表中标记为只读的页面(例如共享库代码、只读数据段)。

与Windows和C++关联: WP标志对于Windows内核态代码的安全至关重要。它确保了即使在Ring 0下,内核也必须遵守页表中的写权限设置,无法随意修改受保护的用户内存。这增强了系统的整体稳定性与安全性。在编写Windows驱动或进行内核开发(通常使用C/C++)时,理解WP标志及其影响非常重要,特别是在涉及到修改内存页面权限的场景(虽然不应随意修改)。一些Rootkit可能会尝试清除WP位来隐藏自己对内存的修改,这是一种经典的内核攻击手段。

PG (Paging Enabled – 分页启用标志):

位置: Bit 31

作用: 当PG设置为1时,启用分页机制。分页机制将线性地址转换为物理地址,并提供了基于页的内存保护功能。几乎所有的现代操作系统(包括Windows)都使用分页来管理内存。

与Windows和C++关联: PG标志是Windows内存管理的基础。C++中的指针操作、变量访问等都依赖于分页机制将程序使用的虚拟地址转换为物理内存地址。分页机制结合页表项(PTE)中的权限位(读、写、执行)实现了内存隔离、进程地址空间独立、虚拟内存、DEP(数据执行保护)。DEP很大程度上依赖于分页机制:如果一个页面被标记为不可执行(通过PTE中的NX/XD位,需要CR4寄存器配合),CPU在PG启用时就不会允许在此页面执行代码。任何试图违反页表权限的操作(例如,向只读页面写入数据,从不可执行页面读取并执行代码)都会导致页面错误(Page Fault),由操作系统内核的异常处理程序接管,通常会导致程序崩溃或被终止。

CR3:

顶级页表的物理基地址

共享内存怎么实现

内存映射文件,依赖页表实现

windows下有哪些注入方式?怎么实现?(重点)

用户层:inline hook,5字节7字节,iat hook修改程序导入表中的函数地址,eat hook修程序内存中加载的模块中的导出表。

windows下3环向0环的切换过程?

kernel32.dll -> kernelbase.dll -> ntdll.dll -> sysenter/syscall -> ssdt表查函数 -> ntoskrnl.exe

如何防止内存被扫描?

如何隐藏进程?(说了一个CPU控制区找EPROCESS断链)隐藏之后对进程运行有影响吗?

Windows进程间通信

剪贴板、异步消息 (PostMessage) 不阻塞发送者,同步消息 (SendMessage) 阻塞发送者直到接收者处理完毕。、

漏洞利用

windows/linux基本保护机制(栈执行保护,基址随机化,代码段随机化,栈溢出保护)

怎么绕过?

堆漏洞利用?(double free, UAF)

栈上漏洞利用有哪些

SQL注入、XSS攻击原理?

ARP欺骗怎么实现的?

如何判断远端服务器的操作系统?

其他八股

https://interviewguide.cn/notes/03-hunting_job/02-interview/01-01-01-basic.html

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇