《加密与解密》个人阅读笔记 四(上)

前言

1.稍微看了看第四章,发现挺多内容是我没有掌握的,在这篇博客里,我尽量把这些内容讲明白
2.由于博客篇幅原因,这篇博客就只记录比较难懂的内容,其他内容请自己看书学习
3.第四章内容实在太多了,我打算分成上下两篇博客:(

本文参考资料:《加密与解密》 《Windows程序设计(第七版)》《Primer c++》Win32API大全 还有一些博客

让我们开始吧----哈↗哈→哈↘哈↗嘻↗嘻→嘻↘嘻↗(自行脑补声音)
在这里插入图片描述

32位程序逆向技术

书中说,在编写32位程序时,首先要实现WinMain函数。WinMain函数和main函数一样,是程序的进入点。

因为我从来没有开发过32位程序,所以从来没有手动调用过WinMain函数。
以下内容来自《Windows程序设计(第七版)》

补充一下Windows程序开发的知识
这是一个c语言版本的Hello World程序

#include<stdio.h>
int main()
{
	printf("Hello World");
}

这是“同样效果”的Windows程序

#include <windows.h> 
int WINAPI WinMain ( HINSTANCE hInstance, HINSTANCE hPrevInstance, 
 PSTR szCmdLine, int iCmdShow) 
{ 
	MessageBox (NULL, TEXT ("Hello, Windows 98!"), TEXT ("HelloMsg"), 0); 
	return 0 ; 
}

书中的IDE为vc6.0 ,这个IDE现在已经过时了,可以用vs代替

运行结果如下
在这里插入图片描述

分析这个windows程序代码

WinBase.h中可以找到WinMain函数的定义

int
#if !defined(_MAC)
#if defined(_M_CEE_PURE)
__clrcall
#else
WINAPI
#endif
#else
CALLBACK
#endif
WinMain (
    _In_ HINSTANCE hInstance,
    _In_opt_ HINSTANCE hPrevInstance,
    _In_ LPSTR lpCmdLine,
    _In_ int nShowCmd
    );

介绍WinMain函数参数

  • hInstance 为应用程序当前事例的句柄
  • hPrelnstance:应用程序的前事例的句柄。对于一个32位的程序,该参数总为NULL
  • lpCmdLine:指向应用程序命令行的空字符串的指针,
  • nCmdShow:指明窗口如何显示 (在上面的代码中没有用到)

句柄是什么?

介绍函数调用

介绍一下WINAPI:在minwindef.h文件中,可以发现以下定义

#define WINAPI      __stdcall

函数传递参数有3种方式,分别是栈方式、寄存器方式及通过全局变量进行隐含参数传递的方式。__stdcall 是函数的调用约定中,利用栈传递参数的方式之一,用于规定参数压入栈的顺序等等问题。

关于__clrcall,我是有查到一些资料啦,但是以我目前的水平看不懂。。。
关于__stdcall,可以看看这一篇博客:带你玩转Visual Studio——调用约定__cdecl、__stdcall和__fastcall

总结一下:stdcall有以下的特点

  • 函数参数从右到左入栈(需要知道这点,才能理解一些pwn的漏洞)
  • 函数的返回值存在EAX寄存器中。函数返回时会自动清理堆栈(也就是书中说的由子程序来平衡栈)

什么是栈平衡?
当函数被调用时,需要申请栈空间来存放局部变量,函数参数等等,当函数调用结束后,需要释放申请的栈空间,保证栈的内容和函数调用前一致

接下来书中分析test2(Par1,Par2)的汇编代码,可以同时参考这篇博客进行理解,这篇博客将ebp,esp的操作用图像表现出来:栈帧ebp,esp详解顺便一提,这篇博客函数参数m,n入栈顺序好像错了

注意:由于栈是向下增长的,所以 sub esp 8 可以在栈中留出一段空间


数据结构

数据结构是计算机存储、组织数据的方式。书中介绍了怎么判断局部变量,全局变量,数组等等

局部变量

学习c语言的时候,我们知道栈中存放函数的参数和返回地址,以及局部变量。其实局部变量不仅能存在栈中,也能存在寄存器中。
首先需要了解栈是怎么对局部变量分配空间的,有以下三种用汇编语言表示的方式:

序号123
sub esp nsub esp -npush reg
add esp nadd esp -npop reg

操作1和操作2都直接操作栈顶指针,直接开辟栈的空间。操作3将寄存器弹入栈或者弹出栈,esp寄存器的值会间接改变。

创建局部变量的两种汇编语句,第一种是mov [ebp-xxx] x ,在当前的栈帧里,ebp应该会在最开始被赋值,局部变量进入栈的时间一定是在ebp赋值之后。所以是[ebp-xxx]而不是[ebp+xxx]

第二种操作是push xxx , 就是将数字弹入栈中

关于全局变量和数组,书中讲得挺详细的,理解难度应该不大

虚函数

如果不知道虚函数是啥,建议先了解一下,再接着学习下面的知识
可以阅读《Primer C++》第15章:面向对象程序设计。

简单来说:对于某一些函数,派生类希望它覆盖基类的函数,而不是直接继承。基类就会将这些函数声明为虚函数。

按照书中的解释,所有虚函数的地址都会放在一个虚函数表(VTBL)中。其他内容自己看书吧,不难理解。才不是我懒得写呢,哼^_^

分析“纯算法实现逻辑判断”示例程序

书中的代码如下

int main(void)
{
	if(FindWindow("计算器",NULL))
		return 1;
	else 
		return 5;
}

汇编语句如下

00401000 push 406030                   ;/Title="计算器" 
00401005 push 0                        ;iclass = 0 
00401007 call dword ptr[40509c]        ;\FindwindowA 
0040100D neg eax 
0040100F sbb eax, eax 
00401011 and al  0FC 
00401013 add eax, 5 
00401016 retn

这段汇编语句的具体分析,我在网上找到了相应的文章neg eax sbb eax, eax

注意:0FC不是0,它是一个二进制数:1111 1100

如果eax的值为0,那么这段代码结束后,eax的值是5
如果eax的值不为0,那么这段代码结束后,eax的值为1 (0FC+5,并且高位截断)


在这里插入图片描述 这段没有看懂,先跳过。。。。。


本文结束,接下来是meme环节


学不明白,崩溃大哭 be like↓
在这里插入图片描述
学明白了,露出纯真笑容 be like↓
在这里插入图片描述

后记

第四章难度突然上去了,但是仔细研究后,感觉自己对程序的理解又进了一步

这几天在网上冲浪,看到了一些感觉挺厉害的文章

  • 拖了这么久的cs61A终于结束了,第四个project真的好难:(

  • 顺便照着《qt6 c++开发指南》重现了文件管理系统,虽然没有看懂代码,但还是copy出结果了
    hu

  • 11
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值