加密与解密 基础篇/win API/小端序大端序

news/2024/12/11 17:22:40/

目录

1.1加密和解密的概念

软件逆向工程

逆向分析技术是什么

1.通过软件的执行 来分析程序

2.静态分析技术

3.动态分析技术

那我们如何有效的进行动态调试呢

1.2文本字符

ASCII码

Unicode

 字节存储顺序

1.3Windows操作系统

win32API函数

WOW64

Windows消息机制

深入理解windows 消息机制_system.windows.interop.msg message 值解释_大林子先森的博客-CSDN博客

虚拟内存


1.1加密和解密的概念

是侧重于windows 的加密保护和解密技术

首先我们先要了解

软件逆向工程

可执行程序->反编译->源代码这就是逆向工程

接着

逆向分析技术是什么

静态调试 和动态调试 主要分为这俩类

1.通过软件的执行 来分析程序

我们可以通过阅读程序的执行 或者说明 来了解程序是怎么执行的

2.静态分析技术

通过IDA这种软件 可以实现静态分析

主要是通过人机交互实现 在用户输入的正确 错误来判断 程序

3.动态分析技术

如果我们需要了解细节 静态调试 还是不够的 所以我们需要通过动态调试

可以说 静态调试 是我们的第一步

动态跟踪 才是分析软件的关键

主要工具有 OllyDbg WinDbg等 

对软件进行一步一步的分析

这里就出现 为什么要进行动态分析的疑问

程序执行 有的时候不是一个函数就执行结束
是多模块的执行结果 
前一个执行结果是后一个输入结果是常有的事情
只有跟踪得到前一个的结果 我们才可以看到后面的事情
并且 如果出现switch这种函数 会有许多分支 如果单单使用静态
是无法得出结果的并且 在程序执行的时候 有一些 是开始的程序对后面程序的初始化
并不依靠重定向如果一个程序 具有加密程序 防止非法阅读 这就是需要动态调试加密程序既要阻止跟踪 又要对下一程序的明文进行解密 如果单单依靠静态
是无法得到的

那我们如何有效的进行动态调试呢

(1)对软件进行粗跟踪
就是进行大块大块的跟踪 遇到 CALL REP LOOP指令的时候
不进行跟踪 而是根据执行结果 判断程序的运行因为程序开始执行 只有一个关键程序是我们需要的
如果每一个程序都细心分析 那么就浪费时间这里就需要注意 如何设置断点需要了解Win32 API函数例如 拦截对话框 
我们就要对MessageBoxA函数进行拦截 对这个函数进行断点 
程序只要一调用这个函数 就会进行中断对这个函数进行断点 我们就可以对这个函数的执行进行判断(2)对关键部分进行细跟踪这个是建立在对程序进行粗跟踪后 我们就可以得到我们需要分析的模块
这样 我们就可以对我们关心的程序进行具体 详细的跟踪一般情况下 我们需要对关键部分进行多次的跟踪 才可以了解程序的执行每一次都记录下来 关键的中间结果和指令地址 这样就会对分析有很大的帮助

1.2文本字符

我们最熟悉的就是ASCII码

ASCII码

是通过 7位二进制 来表示 128个字符

百度百科上就能找到

因为ASCII 只能表示 128字符 所以 有了通过ASCII的衍生和扩展

Unicode

是一个ASCII的扩展 在windows中 通过2字节对其进行编码

所以 我们也称呼 Unicode为 宽字符集

使用 0~65535的双字节无符号数 对每个字符进行编码
所有字符都是 16位的 其中所有的7位ASCII都被扩展为16位的Unicode
(这里高位扩充的 都为0)
例如 pediy的ASCII码是70h 65h 64h 69h 79h其Unicode码为0070h 0065h 0064h 0069h 0079h这里我们需要知道Intel处理器 在内存中将一个字存入存储器 需要占用相继的2个字节并且这个字符 在存放的时候 是按照Little-endian方式存入低位字节存入低地址 高位字节存入高地址

 字节存储顺序

这里就是上面的 Little-endian

这里就是 字节该以什么方式进行传输
Little-endian(小端序)
低字节存入低地址 高字节存入高地址
Big-endian(大端序)
高字节存入低地址 低字节存入高地址

12345678h 存入方式

一般来书 
x86系列CPU都是小端序 Little-endian存入方式PowerPc通常是大端序 Big-endian存入方式注意 大端序在网络协议中 经常使用 所以也叫做 网络字节序

1.3Windows操作系统

win32API函数

对调试程序 是要和系统基层打交道 所以我们需要了解API函数的基础

对我来说 API 我只知道是一个接口

而API其实是 应用程序编程接口

对于 windows开始占据主导位置windows需要开发出为人提供的应用程序但是windows编程人员 只有 API函数这个函数提供应用程序需要的 对内存管理 窗口管理 图形设备接口等服务功能这些功能 通过 函数库 组合在一起叫做 Win APIWin API子系统 负责将API调用 转换为 windows操作系统的系统服务调用可以认为 API就是windows框架的基石他下面是 windows系统操作核心 上面是应用程序

 这里就是开始枯燥的解读

16位的windows API叫做 Win16 (Windows 1.0~3.1)用于 32位的windows的API叫做 Win32 (windows 9x/NT/2000/XP/7/10)64位的windows API的功能和名称 基本没有变化
还是使用的是32位的函数名 只不过是通过 64位代码实现API调用在Win16到Win32的转变中 保持兼容 并且在功能和数量上进行了增加Windows 1.0 只有 不到450个函数 现在已经有几千个了
所有的32位windows 都支持 Win16 API(确保和旧程序的兼容)和Win32 API(确保新程序的运行)在windows NT/2000/XP/7和windows 9x 的工作方式不同在windows NT/2000/XP/7中 Win16函数是通过 一个转换层 来变为 Win32函数调用
然后再被系统处理在windows 9x中却相反 win32函数调用 是通过 转换层 转换为win16函数调用 
然后再被系统处理
因为windows 9x 使用的是 16位代码模式
而windows NT/2000/XP/7 使用的是32位代码模式 
所以是不一样的
windows 的运转核心是动态链接
windows提供了非常丰富的应用程序可利用的函数调用这些函数调用 采用动态链接库 DLL 实现在windows 9x中 DLL 位于 \WINDOWS\SYSTEM子目录中windows NT/2000/XP/7中 DLL位于系统安装目录的 \SYSTEM和\SYSTEM32子目录中在早期的系统 
windows主要依靠3个动态链接库 实现 分别代表了windows 3个子系统Kernel(由Kernel32.dll)实现 :操作系统核心功能服务 主要包括了
进程和线程的控制 内存管理 文件访问等User(由USER32.DLL)实现:负责处理用户接口 包括键盘 鼠标的输入,窗口和菜单管理等GDI(由GDI32.DLL)实现:图形设备接口,允许程序在屏幕和打印机上显示文本和图像

除了上面的模块 windows还提供了很多的DLL 来支持更多的功能

包括 对象安全性,注册表操作(ADVAPI32.DLL)

公共对话框(COMDLG32.DLL)

用户界面外壳(SHELL32.DLL)

网络(NEWAPI32.DLL)

Win API是基于 C语言的接口

但是 Win API 可以通过不同的语言进行编写的程序调用

Unicode影响了计算机的每个部分对操作系统和编程语言的影响最大NT系统是使用Unicode标准字符集进行开发其核心完全使用 Unicode函数工作的 
如果希望调用一个windows函数 并且传递他一个ANSI字符串(是一个扩展的ASCII字符集)系统会先把ANSI字符串转为Unicode字符串
然后进行传入操作系统如果程序希望返回ANSI字符串那么系统会把Unicode字符串变为 ANSI 然后返回所以 在NT框架下 win32 API 能接受 Unicode和ANSI 两个编码方式但是他的内核 只能接受Unicode字符集虽然这些对于用户都是透明的 但是转换字符串需要消耗资源
在Win 32 API函数字符集中 "A"表示 ANSI "W"表示 Widechars(就是Unicode)
ANSI通常是单字节方式
Unicode通常是宽字节方式 这样可以处理双字节字符如果程序在编写的时候 使用了MessageBox函数 
就会去调用这个函数 可是实际上 在USER32.DLL中 
并不会存在这个函数的入口 而是存在 MessageBoxA 和MessageBoxW 这两个函数入口而这不是我们自己选择的 在我们调用了MessageBox函数
开发工具的编译模块 就会自动根据设定来决定使用A 还是 W 直白的说 MassageBox是一个宏定义 在不同环境下变为A W类型

这里给出MassageBox函数的原型 这个函数主要是在用户模块中创建和显示信息框

int MassageBox{HWND hwnd,       父窗口句柄LPCTSTR lpText,    消息框文本地址LPCTSTR lpCaption,    消息框标题地址uint uType    消息框样式
};

我们可以再看一看windows 2000中 MassageBoxA函数的内部结构

int MassageBoxA{MessageBoxExA{  调用这个函数 MessageBoxExA函数MBToWCSEx()  将MessageBoxA的消息框的主体文字转换为 Unicode字符串MBToWCSEx()  将MessageBoxA的消息框的标题栏的文字转为Unicode字符串MessageBoxExW() 调用这个函数 MessageBoxExWHeapFree() 释放内存}
};

MassageBoxExA其实是一个替换翻译层 用于分配内存

并且把 ANSI字符串变为Unicode字符串

所以系统调用Unicode的MassageBoxExW执行

所以如果应用程序是ANSI版本的 就需要更多的内存和CPU资源

如果是Unicode版本 就是符合NT框架 执行效率就会快很多

win32程序大量调用系统提供的API函数 在win32平台的OllyDbg

恰好有对API函数设置断点的强大功能 所以掌握常见API函数的 用法 会给程序的跟踪调试带来大的方便

WOW64

WOW64是64位操作系统上的子系统 可以使大多数32位程序应用在不修改的情况下运行在64位上

64位的windows 除了带有64位操作系统应有的系统文件 还带着32位系统的系统文件

64位系统的系统文件存放在SYSTEM32的文件夹中 在\Windows\system32文件夹中

包含着原生的64位映像文件

为了兼容32位程序 还增加了\Windows\SysWOW64文件夹 里面就存放着32位系统文件

64位程序 会加载System32目录下64位的kernel32.dll user32.dll ntdll.dll
当32位程序开始加载的时候 WOW64会建立32位的ntdll.dll所要求的环境
并且把CPU模式变为32位模式
并且开始执行32位的加载器
这样就会像在32位的机器上一样WOW64会对32位的ntdll.dll调用重定向到ntdll.dll(64位) 
而不是发出原生的32位系统调用指令 WOW64接着重新转回64位模式
捕获系统调用有关的参数 发出64位的系统调用 如果原生系统返回了
WOW64在返回32位模式之前 将所有输出参数从64位转为32位简单来说WOW64为32位程序提供虚拟的32位环境
然后如果需要API的时候 先到64位中找到对应的API 然后翻译成32位的
然后输入给程序

Windows消息机制

Windows是一个消息驱动式系统 windows消息提供在应用程序和应用程序之间、应用程序和Windows之间

应用程序想要实现的功能 由消息触发 通过消息的响应和处理完成

Windows系统有两个消息队列 :
系统消息队列
应用程序消息队列计算机的所有输入设备都是Windows监控
每当一个事情发生的时候 Windows先把输入 的消息放入系统消息队列
再把输入的消息复制到相对应的应用程序队列中 
应用程序中的消息循环在他的消息队列中检索每个信息 
然后发送给相应的窗口函数每一个事情的发生 都要经历上面的过程消息是非抢先性 就是 无论时期是否急缓 都是按照到达进行排队
(一些系统消息除外) 所以容易导致一个实时事情无法及时处理

因为Windows本身是由消息驱动的 所以在调试跟踪的时候 会得到一个相当底层的答案

下面是Windows常见的消息函数

SendMessage函数
这个函数作用是调用一个窗口函数 将一条消息发给那个窗口 
除非消息处理完毕 否则函数不会返回LRESULT SendMessage{HWND hWnd,     目的窗口的句柄   HWND 是一个数据类型 代表一个窗口的句柄UINT Msg,        消息标识符        UINT无符号整数WPARAM wParam,    消息的WPARAM域LPARAM LParam        消息的LPARAM域
};如果消息投递成功 就返回 TRUE
WM_COMMAND消息
当用户从菜单或者按钮中选择一条指令或者一个控件的时候
把他发送给他的父窗口的
或者 一个快捷键被释放时发送下面是C++对WINUSER.H的定义 WM_COMMAND所对应的16进制是 0111hWM_COMMANDwNotifyCode = HIWORD(wParam);      通告代码wID = LOWORD(wParam);              菜单条目 空间或者快捷键标识符hwndCtl = (HWND)lParam;            控件句柄返回值 如果应用程序处理了这个消息 那么返回值为0
WM_DESTROY
当一个窗口被销毁的时候 发送这个消息 该消息的十六进制是 02h 没有参数返回值 如果应用程序处理这个消息 那么返回值为 0 作用就是销毁程序 释放内存
WM_GETTEXT
应用程序发送一条WM_GETTEXT的消息 把一个对应窗口的文本复制到一个由呼叫程序提供的缓存区中 
这个的十六进制是 0DhWM_GETTEXTwParam = (wParam) cchTextMax;    需要复制的字符数lParam = (LPARAM) lpszText;       接受文本的缓存区地址返回值 是被复制的字符数
WM_QUIT
当系统调用 PostQuitMassage函数的时候 生成 WM_QUIT消息 十六进制是 012hWM_QUITnExitCode = (int)wParam;     退出代码没有返回值停止循环 退出程序
WM_LBUTTONDOWN 
光标停在一个窗口的客户区 并且按下左键的时候 WM_LBUTTONDOWN发生消息
如果光标没有被捕获 就发给光标下的窗口 如果捕获了 就发送 已经捕获动作的窗口WM_LBUTTONDOWN
fwKeys = wParam;                key旗帜
xPos = LOWORD(lParam);          光标的水平位置  
yPos = HIWORD(lParam);          光标的垂直位置返回值 如果应用程序处理了这条消息 那么返回值为0

深入理解windows 消息机制_system.windows.interop.msg message 值解释_大林子先森的博客-CSDN博客

虚拟内存

默认情况下 32位 Windows操作系统的地址空间在4GB内 win32点平坦内存模式

可以让每一个进程都有自己的虚拟空间

对32位进程来说 这个地址空间是4GB

因为32位指针有00000000h~FFFFFFFFh 的任意值

这个时候 程序的代码和数据都存放在同一地址空间中 不需要区分代码段和数据段

虚拟内存并不是真实的内存
他是通过映射的方式 把可用虚拟内存地址可以达到4GB大小
所以每一个程序可以得到2GB的虚拟地址 剩下的2GB留着操作系统自用在 Windows NT 应用程序甚至可以得到3GBWindows 是一个分时的多任务操作系统 
CPU时间 再被分成一个一个时间片后分配给不同的程序
在一个时间片中 和这个程序不相干的不会映射到线性地址中 
所以每个程序都有自己的4GB寻址空间 互不干扰 
在物理内存中 操作系统和系统DLL代码需要供给每一个程序调用
所以他们在任意时刻都被映射 
用户的 EXE程序 只会在执行的时间片中被映射 用户 DLL则是有选择的被映射
下面是虚拟内存的实现方法和过程1 应用程序执行启动 操作系统创建一个进程 给这个程序分配2GB的虚拟地址(只是地址 不是空间)
2 虚拟内存管理器把应用程序的代码映射到和应用程序虚拟地址中的某个位置 并且把当前需要的代码写入物理地址(虚拟地址和应用程序代码在屋里内存中的位置是没有关系的)
3 如果使用DLL DLL也会被映射到虚拟地址空间中,在需要的时候才会写入物理地址
4 其他项目(数据,堆栈等)的空间从物理内存进行分配 然后被映射到虚拟地址空间中
5 应用程序通过使用其虚拟地址空间的地址 开始执行 然后 虚拟内存管理器把每次内存访问映射到物理地址总结应用程序不会直接存入物理空间中
虚拟内存管理器通过虚拟地址的访问请求来控制所有物理空间的访问
每个程序都有自己独立的4GB空间 不同应用程序的地址空间是相互隔离的
DLL程序没有自己的空间 他们总是被映射到其他应用程序的地址空间中 作为一部分进行执行
(因为如果DLL不和应用程序处于同一空间 就无法调用DLL)使用虚拟内存的好处是 简化了内存的管理 弥补了内存的不足 可以防止多任务下程序的冲突

在64位CPU最大的寻址空间是 16TB

实际应用中

64位的windows 7 支持8~192GB点聂村

64位windows 10 支持 128GB~2TB的内存


http://www.ppmy.cn/news/79780.html

相关文章

探秘 | 简说IP地址以及路由器的功能究竟是什么?

我们都知道我们在上网的时候都有一个IP地址,用来和其他人进行通信和数据交换。 其中IP地址又分为内网地址和外网地址,也叫作私有地址和公有地址。 为什么要区分私有地址和公有地址呢?原因很简单,因为公有的IP地址不够使用了&…

Python基础教程:第九章_Python异常模块与包

从现在开始,让我们来进入到新的章节, Python 异常模块与包的内容学习。本章节我们主要分为 6 部分进行讲解,包含了 Python 异常的相关操作以及 Python 的模块操作, Python 的包操作和安装第三方 Python 包的相关操作。 了解异常 …

周六晚周日全天Hcip BGP

ISIS 默认是窄带 需要开启宽带 ISIS,前提我是level 1,收到ATT位置为1 的路由是默认路由 为什么要使用BGP协议? 我们要在不同的AS之间进行通信,需要使用BGP协议。 BGP优势: 1.非常稳定 2.可以传输大量的路由&#xff…

Python——第7章 pandas数据分析实战

7.1pandas常用数据类型 7.1.1一维数组与常用操作 import pandas as pd import matplotlib.pyplot as plt#设置输出结果对齐方式 pd.set_option(display.unicode.ambiguous_as_wide,True) pd.set_option(display.unicode.east_asian_width,True)#自动创建从0开始的非负整数索引…

装饰者模式-java实现

的简介 装饰模式又称为“包装(Wrapper)模式”,以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。动态地给对象添加一些额外地职责,就增加功能而言,装饰模式比生成子类更加灵活。 一般来说,一些特殊场景…

边缘计算AI硬件智能分析网关V1版的接入流程与使用步骤

我们的AI边缘计算网关硬件——智能分析网关目前有两个版本:V1版与V2版,两个版本都能实现对监控视频的智能识别和分析,支持抓拍、记录、告警等,在AI算法的种类上和视频接入上,两个版本存在些许的区别。V1的基础算法有人…

一文3000字从0到1使用Selenium进行自动化测试

对于很多刚入门的测试新手来说,大家都将自动化测试作为自己职业发展的一个主要阶段。可是,在成为一名合格的自动化测试工程师之前,我们不仅要掌握相应的理论知识,还要进行大量的实践,积累足够的经验,以便快…

【P29】JMeter IF 控制器(If Controller)

文章目录 一、IF 控制器(If Controller)参数说明二、测试计划设计2.1、groovy 写法2.2、javaScript 写法2.3、jexl3 写法 一、IF 控制器(If Controller)参数说明 可以控制其下面的子/后代元素是否执行;如果为 true 则…