学习使用idle和vs code书写python,

核心内容摘要

电源进阶05 开关电源PFC技术解析——从无源到有源的效率革命
流式接口是什么

嵌入模型与Chroma向量数据库 - Chroma安装与简单应用实例 - AI大模型应用开发必备知识

背景在CTF比赛中, CTF逆向题目除了需要分析程序工作原理, 还要根据分析结果进一步求出FLAG。

逆向在解题赛制中单独占一类题型, 同时也是PWN题的前置技能。

在攻防赛制中常与PWN题结合。

CTF逆向主要涉及到逆向分析和破解技巧这也要求有较强的反汇编、反编译、加解密的功底。

CTF中的逆向题目一般常见考点

常见算法与数据结构。

各种排序算法, 树, 图等数据结构。

识别加密算法与哈希算法代码特征,识别算法中魔改的部分。

代码混淆, 代码虚拟化, 修改代码流程, 反调试等。

软件加密壳是软件保护技术的集中应用。

CTF逆向题目两大主题暴力破解、算法分析破解

暴力破解通过修改汇编代码而跳过程序内部校验部分从而改变程序的正常逻辑最后满足题目要求来获取flag。

这就考验在逆向分析样本时候对样本验证代码定位能力。

算法破解这主要需要分析样本中的加密部分的汇编代码将其加密算法进行还原并根据分析结果写出对于的解密程序最后算出flag。

这就考验了对样本分析过程中的耐心和扎实的逆向能力和一定的代码开发能力。

逆向解题常见技巧

逆向分析与功能猜测结合, 通过逆向分析进行缩小猜测范围, 猜测为逆向指出方向, 逆向再验证猜测的思路。

结合样本中汇编代码上下文与整体程序功能, 关注程序中给出的文字提示信息。

实际比赛的逆向题目多数是为出题而出题, 有目的性强, 功能结 构单一, 无关代码少等特点。

遇到程序代码量极大时, 可以先判断是否引用了较多的开源的代码, 而程序的主逻辑相对简单。

逆向基础CTF逆向常用工具Ollydbg、IDA、PCHunter、Exeinfo PE(PeTool)、CFF Explore、exeScope、ApiMonitorTrial、winhex。

CTF逆向需涉及知识点汇编知识window下的X86和X64; android下的ARM和ARM64。

文件结构windox下的PE文件; android下的dex文件和ELF文件。

反调试技术:window和android下的调试和反调试对抗技术。

加壳和脱壳PE的加壳和脱壳、 ELF和dex的加壳和脱壳。

开发能力C、C、python等语言的开发能力。

CTF样本逆向解题流程

突破保护获得样本程序时先用ExeInfoPePE工具进行查看程序属于哪平台下的例如windows X86/X

android、linux等是否采用代码保护措施例如代码混淆、保护壳、各种反调试等如果有那么在进行分析样本之前需要先过掉样本混淆、脱壳、反反调试等技术来去除或绕过这些保护措施。

定位关键代码我们需要将目标软件进行反汇编然后结合IDA和OD快速定位到关键代码例如验证函数、关键字符串信息、程序导入表。

动静结合我们找到程序的关键代码之后就要对其进行详细的逆向分析。

如果程序在IDA中F5可以生成伪代码那么我们就先根据伪代码进行静态分析然后模糊不清的地方可以结合ollydbg工具进行动态调试观察来验证自己的猜想。

破解验证算法通过详细逆向分析完程序的关键代码(例如:验证算法)之后接着就要根据分析出的结果进行暴力破解或者进行算法解密代码的编写以此来获取或生成flag。

CTF中常见的验证算法

直接比较验证密钥一般没有经过加密直接跟内置程序中的key进行比较(也就是硬编码方式比较)此类题型比较简单。

加密比较验证密钥一般会进行如异或、base

MD

RC4等形式的加密此类题型需要识别出其加密方式然后再根据其算法特点还原出相应的key值现实CTF比赛中可能出现密钥用不同加密算法分段加密或嵌套验证等多种加密组合起来的方式也需要去深入识别分辨。

逆向自定义实现的算法这类题目就需要去逆向题目作者自己编写实现的算法了这样的算法难度相对比较难在逆向过程中需要识别出其是算法问题题目然后分析出其每个函数代表什么操作来进一步解题需要逆向算法的题目一般都比较难需要理清算法实现思路跟踪自己输入的数据使用算法进行了哪些处理最后变成了什么和什么比较需要有一定的耐心和细心建议多加练习。

其他类型的加密题目实在解不出来的也可以尝试是否可以绕过或暴力破解穷举等方式。

定位关键代码的方法

顺序跟踪法如果拿到的样本程序相对较小代码量不多且主函数入口好找即可使用顺序跟踪法从程序主函数入口顺序跟踪一步步分析完整的程序执行过程基本就能知道程序的验证部分了至于各个类型程序主函数的查找方法大家可以自行百度这里还需要分清楚程序入口点和main函数的区别大家一般需要找main函数但也不全是找main函数如果遇到了MFC的程序大家还需要根据具体情况具体分析如果有条件大家也可以编码实现相应程序然后反汇编来进行练习查找程序的主函数这个需要平时多练习、多积累、多

总结。

字符串查找如果给定的样本程序没有做混淆处理而且还有比较明显的字符串信息提示那么就可以根据程序运行的提示使用字符串查找功能查找程序所提示字符串的方式来反向查找其被引用的地址。

例如IDA中shiftF12的字符串窗口OD中查找-所有参考文本字串字符串搜索的优先级很高很多情况下对我们解题很有奇效所以拿到程序后可以优先字符串查找尝试。

系统函数断点如果程序非常大而且也没有啥字符串提示信息可以利用那么我们就可以猜测根据样本程序所使用的函数来定位关键验证代码这需要掌握C语言或C语言还有windows核心编程的知识熟悉一些通用函数具有的功能例如程序出现了一个弹窗那么程序就有可能调用了MessageBox这个函数如果程序出现了输出那么程序就有可能调用了printf这个函数等等所以可以通过程序所表现出的状态来下相应的函数断点然后栈回溯反向查找其引用位置进而找到关键代码。

汇编基础(以下知识点只起到抛砖引玉的作用)X86汇编32位CPU有16个寄存器,32位寄存器存放的是4个字节的数据它们名称分别为4个数据寄存器(EAX、EBX、ECX和EDX);2个变址和指针寄存器(ESI和EDI);2个指针寄存器(ESP和EBP);6个段寄存器(ES、CS、SS、DS、FS和GS);1个指令指针寄存器(EIP);1个标志寄存器(EFlags)。

X64汇编64位CPU有16个通用寄存器寄存器存放8个字节数据它们名称分别为rax,rbx,rcx,rdx,rsi,rdi,rsp,rbpr8,r9,r10,r11,r12,r13,r14,r1532位使用栈帧来作为传递的参数的保存位置而64位使用寄存器分别用rdi,rsi,rdx,rcx,r8,r9作为第

个参数。

rax作为返回值。

64位没有栈帧的指针32位用ebp作为栈帧指针64位取消了这个设定rbp作为通用寄存器使用。

rax 作为函数返回值使用。

rsp 栈指针寄存器指向栈顶rdirsirdxrcxr8r9 用作函数参数依次对应第1参数第2参数。

rbxrbpr12r13r14r15 用作数据存储遵循被调用者使用规则简单说就是随便用调用子函数之前要备份它以防他被修改。

r10r11 用作数据存储遵循调用者使用规则简单说就是使用之前要先保存原值。

通用汇编知识函数(Call)的3种调用约定_cdecl,_stdcall、_fastcall_cdecl是C语言的默认的函数调用方法所有参数从右到左依次入栈这些参数由调用者去清除。

堆栈恢复常用指令add,esp,x x表示参数占用的字节数_stdcall是C标准的函数调用方式所有参数从右到左依次入栈如果是调用类成员的话最后一个入栈的是this指针。

这些堆栈中的参数由被调用的函数在返回后清除使用的指令是ret x其中x表示参数占用的字节数。

_fastcall是编译器指定的函数快速调用方式。

由于大多数函数参数个数很少使用堆栈传递比较费时。

因此_fastcall通常规定前两个参数由寄存器传递其余参数还是通过堆栈传递。

但是不同的编译器编译的程序规定的寄存器不同返回方式一般是ret x。

总结三个调用约定函数参数和局部变量区分函数的局部变量的存在形式mov eax, dword ptr[ebp -4]函数参数表示法mov eax [esparg_0]Arm32汇编(Android)ARM微处理器共有**37个32位寄存器其中31个为通用寄存器6个为状态寄存器。

**但是这些寄存器不能被同时访问具体哪些寄存器是可以访问的取决ARM处理器的工作状态及具体的运行模式。

但在任何时候通用寄存器R14~R

程序计数器PC、一个状态寄存器都是可访问的。

未分组寄存器 **R0 ~ R7**共8个分组寄存器R8 ~ R12R13 ~ R14R8 ~ R12其中FIQ模式下有单独的一组 R8 ~ R12共5个另外 6种模式共用一组R8 ~ R12共5个总共10个R13 ~ R14其中USR和SYS模式表格的第一列共用一组R13 ~ R14共2个另外5种模式下各有独自的一组R13 ~ R14共10个总 共12个程序计数器 PC 即R15共1个分组寄存器R

R14寄存器R13通常做堆栈指针SP寄存器R14用作子程序链接寄存器Link Register-LR也称为LR指向函数的返回地址。

Arm64汇编(Android)汇编中共有34个寄存器。

其中包括31个通用寄存器、SP寄存器、PC寄存器CPSR寄存器。

31个通用寄存器中X0-X30表示是64位的寄存器。

W0-W30表示是32位的寄存器。

X31 :也称为零寄存器它一般用于变量的初始化它也有两表现形式**XZR**表示是64位的零寄存器 它在内存中是用8个字节存储。

WZR表示是32位的零寄存器它在内存中是用4个字节存储。

SP :保存栈指针(栈顶指针)使用SP或WSP来进行对SP寄存器的访问,也就是用于操作局部变量地址。

PC程序计数器PC指针寄存器它用于指向即将要执行的下一条指令。

CPSR状态寄存器FPX29保存栈帧地址栈底指针LPX30通常称X30为程序的链接寄存器保存子程序结束后需要执行的下一条指令。

掌握ARM汇编中基本结构前需要回顾和并熟记以下的条件指令怎样在ARM汇编中去识别和定位出函数

1.

B 跳转指令

1.

BL 带返回的跳转指令

1.

BLX 带返回和状态切换的跳转指令

1.

BX 带状态切换的跳转指令

直接向程序计数器 PC 写入跳转地址值。

通过向程序计数器 PC写入跳转地址值,可以实现在 4GB 的地址空间中的任意跳转,在跳转之前结合使用MOV LRPC

总结识别函数的方法就是汇编指令中是否有包含B、BL、BLX、BX、PC的汇编指令。

ARM函数调用约定采用的是ATPCSATPCS的英文全称是ARM-THUMB procedure call standardARM-Thumb过程调用标准

总结参数1~参数4 分别保存到 R0~R3 寄存器中 剩下的参数从右往左一次入栈被调用者实现栈平衡返回值存放在 R0 中。

函数参数当参数个数小于等于4个的时候使用r0到r3这4个寄存器进行参数传递如果参数个数大于4个余下的参数就通过sp所指向的数据栈进行参数传递。

比如有3个参数的话那么r0代表函数的第一个参数r1代表函数的第二个参数r2代表函数的第三个参数。

比如有6个参数的话那么r0-r3表示前面4个参数然后余下的两个参数通过在栈上开辟8字节的空间进行参数传递。

r0–r3存储传递给函数的参数值多余的参数通过压栈传递。

r4 -r11存储函数的局部变量Thumb模式不会使用r8以后的寄存器r12是内部过程调用暂时寄存器intra-procedure-call scratch register。

r13存储栈指针(sp)。

在计算机中栈非常重要。

这个寄存器保存着栈顶的指针。

这里可以看到更多关于栈的信息。

r14链接寄存器(link register)。

存储着当被调用函数返回时将要执行的下一条指令的地址。

r15用作程序计数器(program counter)。

存储着当前执行指令的地址。

每条执行被执行后该计数器会进行自增(

函数的返回值放到r0中。

fp叫做frame pointer寄存器即栈帧指针寄存器sp叫做stack pointer寄存器即栈指针寄存器。

在ARM指令系统中是地址递减栈入栈操作的参数入栈顺序是从右到左依次入栈而参数的出栈顺序则是从左到右的你操作。

包括push/pop和LDMFD/STMFD等。

函数返回值

结果为一个32位的整数时,可以通过寄存器R0返回。

结果为一个64位整数时,可以通过R0和R1返回依此类推。

结果为一个浮点数时,可以通过浮点运算部件的寄存器f0,d0或者s0来返回。

结果为一个复合的浮点数时,可以通过寄存器f0-fN或者d0~dN来返回。

对于位数更多的结果,需要通过调用内存来传递。

反调试Window反调试技术应用程序通过利用反调试技术可以进行识别判断自身是否被调试当识别到被调试就会改变执行的流程或修改自身自销毁。

从而增加逆向调试的时间和复杂度。

反调试实现的技术

IsDebuggerPresent函数

实现原理只能用于自身进程的检测通过查询进程环境块(PEB)中的IsDebugged标志如果被调试状态那么返回非0调试没有被调试状态返回

NeQueryInfomationProcess函数原理用于提取一个给定进程的信息函数参数1表示进程句柄参数2表示信息类型第二个参数ProcessDebugPort的值如果设置为0x7就可以进行返回句柄标识的进程是否被调试如果处于调试状态那么就会返回调试的端口非调试状态则返回0。

CheckRemoteDebuggerPresent函数

实现原理它可以用于自身进程和其他进程通过查询进程环境块PEB中的ISDebugged标志如果被调试状态那么返回值返回非0没调试状态返回0。

FindWindowA、EnumWindows

实现原理:通过检测运行环境的调试器的窗口信息。

OutputDebigString函数

实现原理调试器调试应用程序的时候是通过触发异常方式进行执行调试功能的通过利用SetLastError函数设置错误码方式并用OutputDebugString函数进行打印出来如果程序再被附加调试状态那么GetLastError获取到的错误码是前面用SetLastError的错误码一致如果没有被调试那么错误码可能是任意值。

注册表检测

实现原理通过查找调试器引用的注册表信息进行判断如果当前环境下的注册表有存在调试器的信息下面是调试器在注册表中的一个常用位置。

SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug(32位系统)SOFTWARE\Wow6432Node\Microsoft\WindowsNT\CurrentVersion\AeDebug(64位系统)该注册表项指定当应用程序发生错误时触发哪一个调试器。

默认情况下它被设置为Dr.Watson。

如果该这册表的键值被修改为OllyDbg(其他的调试器X64dbg、Windbg、ollyIce也一样)则应用程序就可能确定它正在被调试。

BeginDebugged标志检测

实现原理当应用程序运行时候fs:[30h]指向PEB基地址如果指向的BeginDebugged标志位0的情况下那么应用程序没有被调试反之被调试。

检测ProcessHead标志

实现原理在PEB结构中的Reserved数组中有一个未公开的位置ProcessHeap它位于PEB结构的0x18处ProcessHeap中包含ForceFlags标志可以通过该标志进行判断是否处于调试状态。

检测NTGlobalFlag标志

实现原理通过调试器启动的进程和正常创建启动的进程是有差别的所以他们创建内存推的方式也不一样。

NTGlobaFlag标志它是微软未公开的在PEB偏移0x68位置如果值为0x70那么表示程序是调试器启动的。

检测父进程是否是explorer.exe

实现原理正常启动的应用他的父进程是explorer.exe如果进程被调试状态那么它的父进程就是调试器进程。

所以只要父进程不是explorer.exe进程就可以认定为调试状态。

反调试检测小结以上的反调试技术是相对应用比较多的技术对于反调试技术一般是通过多种方案结合的。

反调试技术除了以上的方案还有程序中执行代码段的校验运行的调试器检测调试器的特征码检测断点检测等等。

反调试是逆向的第一个门槛只有跨过这个门槛逆向才能真正开始。

下面针对调试反调试的技术

总结方案可以借鉴学习。

参考链接https://github.com/LordNoteworthy/al-khaserjava层检测

isDebuggerConnected函数检测原理当app被调试的时候调用android.os.Debug.isDebuggerConnected() 返回值为true否则返回值为false。

androiddebuggable标签检测原理Android中的AndroidManifest.xml文件中如果debuggable属性值设置为true那么久表示可以调试属性值为false就表示不可调试。

包签名校验检测原理通过检测app的包签名信息如果包签名不一致那么就是重新打包的。

native层检测

检测自身进程的TracerPid值检测原理可以通过/proc/pid/status或/proc/pid/task/pid/status获取到TracerPid值默认下是0被附加调试会变成调试的PID值。

基于IDA调试器检测检测原理android_server端口号(通过/proc/net/tcp 检测23946端口)、android_server文件信息、调试器进程名、

检测自身进程maps检测原理通过检测/proc/pid/maps检测自身进程是否有保护敏感模块信息来判断是否被调试。

检测父进程zygote进程检测原理因为zygote是所有程序的父进程所有应用app也是通过fork方式创建出来的通过/proc/pid/cmdline获取如果当前父进程不是zygote进程那么久表示被调试了。

检测自身状态检测原理: app在被附加调试过程中会被挂起暂停所以通过/proc/pid/stat或/proc/pid/task/stat获取当第三个字段属性为t时候那么表示app在被调试暂停挂起。

抢占Ptrace检测原理在android系统中一个app只能被ptrace一次。

所以先自己ptrace自己。

android反调试小结由于android系统是开源的所以对于以上利用系统属性及函数用于反调试的都可以通过修改系统源码然后重新编译方式进行过检测。

对于这种修改系统方式其实可以通过自己ptrace自身方式如果自身ptrace后tracePid值还是为0那么表示该系统是重新修改编译过的。

攻防是个不断持续的过程同样反调试和过反调试也是如此。

就在于点高点低了。

以上罗列的只是简单的一些方案。

加壳和脱壳Window加壳方案专门负责保护软件被非法修改或编译的程序。

它附加在原始程序上通过window加载器载入内存后先于原始程序执行以得到控制权在执行过程中对原始程序进行解密、还原还原后把控制权还给原始程序执行原来代码。

它的作用可以有效防止破解者对程序文件进行非法修改也可以防止程序被静态反编译。

不同外壳的侧重方面是不一样的有的侧重压缩有的侧重加密。

例如压缩壳的特点就是减少软件的体积加密保护就不是它的重点。

常见壳的加载过程

保存入口参数

获取壳本身需要使用的API地址

解密原程序各个区块的数据

IAT的初始化

重定位项的处理

Hook API

跳转到程序原入口点(OEP)壳的种类压缩壳有UPX、ASPack、PECompact等等UPX是开源https://upx.github.io/ASPack壳的官网http://www.aspack.com加密壳AsProtect、Armadillo、ExeCryptor等等虚拟机壳Themida、Winlicense、VMProtect等等以上这些壳都可以用ExeInfo PE或PEID工具通过壳特征方式识别出什么类型的壳。

下图中是PEID工具识别壳的特征码Signs文件里面的特征。

window脱壳方案手动脱壳的步骤

查找真正的程序入口点

抓取内存映像文件

重建PE文件定位程序OEP的方法

根据跨段指令进行寻找OEP

用内存访问断点寻找OEP方法:先打开内存模块AltM接着直接对代码段例如.text区段进行下内存访问断点F2这个断点是一次性断点当所在段读取或执行时就中断中断发生后断点将自动删除。

根据栈平衡原理寻找OEP在编写加壳软件时必须保证外壳初始化的各寄存器值和原程序的各寄存器值是相同的。

通常用pushad/popad,pushfd/popfd指令来保存和恢复现场环境。

根据编译语言特点寻找OEP各类语言编译的文件入口点都有自己的特点。

使用同一种编译器编译的程序其入口代码都很类似都有一段启动代码编译器在编译程序时会自动和程序连接。

在完成必须的初始化工作后调用WinMain函数。

Android加壳方案目前市面上加固产品种类:360加固、爱加密加固、梆梆加固、腾讯乐固、网易易盾、几维加固、顶象加固。

一般App源程序加密之后就存放在那几个目录下一般是dex文件尾部libs目录assets目录。

加固后可以通过app包里面的lib文件夹下的特有文件进行识别加固厂商。

网易易盾libnesec.so、libbugrpt.so爱加密libexec.so,libexecmain.soijiami.dat梆梆libsecexe.so,libsecmain.so , libDexHelper.so阿里聚安全aliprotect.datlibsgmain.solibsgsecuritybody.so腾讯安全libtosprotection.armeabi.solibtosprotection.armeabi-v7a.solibtosprotection.x

so娜迦libchaosvmp.so, libddog.solibfdog.so360libprotectClass.so,libjiagu.so libjiagu_art.solibjiagu_x

so通付盾libegis.solibNSaferOnly.so网秦libnqshield.so百度libbaiduprotect.so腾讯libshellx-

2.

10.

6.

solibBugly.solibtup.so, libexec.solibshell.soAPKProtect:libAPKProtect.so几维安全libkwscmm.so, libkwscr.so, libkwslinker.so加固的特点Android脱壳方案脱壳的主要流程:就是在App程序运行起来后将源App的数据内存释放出来后并将释放出来的数据拷贝出来。

内存dump法通过利用frida框架结合脱壳脚本dex-dumphttps://github.com/hluwa/FRIDA-DEXDump通过在app内存中暴力搜索 dex.035或者dex.036 。

通过读取/proc/pid/maps查找后进行dump数据。

hook关键函数法主要利用frida框架进行脚本开发。

通过hook关键函数InMemoryDexClassLoader、dvmDexFileOpenPartial、DexClassLoader,dexFileParse、memcmp然后去dump解密后的dex数据

动态调试法通过动态调试app下mmap函数断点然后去dump出源dex数据。

定制系统法通过修改重编译android系统并刷机。

Hook Dalvik_dalvik_system_DexFile_defineClassNative。

枚举所有DexClassDef对所有的class调用dvmDefineClass进行强制加载

dex2oat法ART模式下dex2oat生成oat时内存中的DEX是完整的。

网络安全学习资源网上虽然也有很多的学习资源但基本上都残缺不全的这是我们和网安大厂360共同研发的的网安视频教程内容涵盖了入门必备的操作系统、计算机网络和编程语言等初级知识而且包含了中级的各种渗透技术并且还有后期的CTF对抗、区块链安全等高阶技术。

总共200多节视频100多本网安电子书最新学习路线图和工具安装包都有不用担心学不全。

这些东西我都可以免费分享给大家需要的可以点这里自取:网安入门到进阶资源

臧精阁3秒后自动进入-臧精阁3秒后自动进入应用

百度百家号客服电话人工服务

123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123