首页 > 其他分享 >[系统安全]加法与减法、乘法与除法优化原理

[系统安全]加法与减法、乘法与除法优化原理

时间:2024-11-22 13:48:59浏览次数:3  
标签:nNum argc 系统安全 esp mov eax push 减法 除法

0x1 加法与减法的优化原理

1.1 加法的识别与优化

加法优化有3种方案:

1)形式1:变量与变量

2)形式2:变量加常量

3)形式3:变量加1

C源代码:

int _tmain(int argc, _TCHAR* argv[])
{
	int nNum, nA = 8;
	nNum = argc + nA;      // 形式1:变量减变量
	printf("%d\r\n",nNum);
	nNum = argc + 9;       // 形式2:变量减常量
	printf("%d\r\n",nNum);
	nNum = nNum + 1;       // 形式3:变量减1
	printf("%d\r\n",nNum);

	return 0;
}

Debug反汇编:

01297710 55            push ebp
01297711 8BEC          mov ebp,esp
01297713 81EC D8000000 sub esp,0xD8
01297719 53            push ebx
0129771A 56            push esi                   ;  9-34.<ModuleEntryPoint>
0129771B 57            push edi
0129771C 8DBD 28FFFFFF lea edi,[local.54]
01297722 B9 36000000   mov ecx,0x36
01297727 B8 CCCCCCCC   mov eax,0xCCCCCCCC
0129772C F3:AB         rep stos dword ptr es:[edi]
0129772E C745 EC 08000 mov [local.5],0x8          ;  nA = 8
01297735 8B45 08       mov eax,[arg.1]            ;  eax = argc 赋值
01297738 0345 EC       add eax,[local.5]          ;  eax = eax + nA;形式1:nNum = agrc + nA
0129773B 8945 F8       mov [local.2],eax          ;  nNum = eax
0129773E 8B45 F8       mov eax,[local.2]          ;  eax = nNum
01297741 50            push eax
01297742 68 508E3201   push 9-34.01328E50         ;  %d\r\n
01297747 E8 C8C5FFFF   call 9-34.01293D14         ;  printf
0129774C 83C4 08       add esp,0x8                ;  堆栈平衡
0129774F 8B45 08       mov eax,[arg.1]            ;  eax = argc
01297752 83C0 09       add eax,0x9                ;  eax = eax + 9;argc + 9;形式2:nNum = argc + 9
01297755 8945 F8       mov [local.2],eax          ;  nNum = eax
01297758 8B45 F8       mov eax,[local.2]          ;  eax = nNum
0129775B 50            push eax
0129775C 68 508E3201   push 9-34.01328E50         ;  %d\r\n
01297761 E8 AEC5FFFF   call 9-34.01293D14         ;  printf
01297766 83C4 08       add esp,0x8
01297769 8B45 F8       mov eax,[local.2]          ;  eax = nNum
0129776C 83C0 01       add eax,0x1                ;  eax = eax + 1;形式3:nNum = nNum+1
0129776F 8945 F8       mov [local.2],eax          ;  nNum = eax
01297772 8B45 F8       mov eax,[local.2]          ;  eax = nNum
01297775 50            push eax
01297776 68 508E3201   push 9-34.01328E50         ;  %d\r\n
0129777B E8 94C5FFFF   call 9-34.01293D14         ;  printf
01297780 83C4 08       add esp,0x8
01297783 33C0          xor eax,eax
01297785 5F            pop edi                    ;  9-34.<ModuleEntryPoint>
01297786 5E            pop esi                    ;  9-34.<ModuleEntryPoint>
01297787 5B            pop ebx                    ;  9-34.<ModuleEntryPoint>
01297788 81C4 D8000000 add esp,0xD8
0129778E 3BEC          cmp ebp,esp
01297790 E8 94ABFFFF   call 9-34.01292329
01297795 8BE5          mov esp,ebp
01297797 5D            pop ebp                    ;  9-34.<ModuleEntryPoint>
01297798 C3            retn

Release反汇编:

00EB1260 push ebp
00EB1261 mov ebp,esp
00EB1263 push esi
00EB1264 mov esi,[arg.1]                                              ;  esi = argc
00EB1267 lea eax,dword ptr ds:[esi+0x8]                               ;  eax = argc+nA;形式1:变量+变量;优化后的加法,精妙!
00EB126A push eax
00EB126B push 9-34.00EC64D8                                           ;  %d\r\n
00EB1270 call 9-34.printf_initialize_sse2_sse2_from_osKeywordOncrt_st>;  printf
00EB1275 add esi,0x9                                                  ;  esi = esi+9;argc+9;形式2:变量+常量
00EB1278 push esi
00EB1279 push 9-34.00EC64D8                                           ;  %d\r\n
00EB127E call 9-34.printf_initialize_sse2_sse2_from_osKeywordOncrt_st>;  printf
00EB1283 lea eax,dword ptr ds:[esi+0x1]                               ;  eax = esi + 1;nNum+1;形式3:变量+1;直接用esi进行地址的存储
00EB1286 push eax
00EB1287 push 9-34.00EC64D8                                           ;  %d\r\n
00EB128C call 9-34.printf_initialize_sse2_sse2_from_osKeywordOncrt_st>
00EB1291 add esp,0x18
00EB1294 xor eax,eax
00EB1296 pop esi                                                      ;  9-34.__argc_log10_table_tk_exit_tableate
00EB1297 pop ebp                                                      ;  9-34.__argc_log10_table_tk_exit_tableate
00EB1298 retn
          

小结:

1)变量+变量 = lea Reg32,[变量+变量]

2)变量+常量 = add 变量+常量

3)变量+1 = lea Reg32,[变量+1]

注:这里的代码我和书里不一样,书中是【变量+1 = inc 常量】

1.2 减法的识别与优化

减法优化与加法大同小异。
C源代码:

int _tmain(int argc, _TCHAR* argv[])
{
	int nNum, nA = 8;
	nNum = argc - nA;      // 形式1:变量减变量
	printf("%d\r\n",nNum);
	nNum = argc - 9;       // 形式2:变量减常量
	printf("%d\r\n",nNum);
	nNum = nNum - 1;       // 形式3:变量减1
	printf("%d\r\n",nNum);

	return 0;
}

Debug反汇编:

00E07710 push ebp
00E07711 mov ebp,esp
00E07713 sub esp,0xD8
00E07719 push ebx
00E0771A push esi                   ;  9-34.<ModuleEntryPoint>
00E0771B push edi                   ;  9-34.<ModuleEntryPoint>
00E0771C lea edi,[local.54]
00E07722 mov ecx,0x36
00E07727 mov eax,0xCCCCCCCC
00E0772C rep stos dword ptr es:[edi]
00E0772E>mov [local.5],0x8          ;  nA = 8
00E07735 mov eax,[arg.1]            ;  eax = argc
00E07738 sub eax,[local.5]          ;  eax = eax - nA; eax = argc-nA;形式1:变量-变量
00E0773B mov [local.2],eax          ;  nNum = eax
00E0773E mov eax,[local.2]          ;  kernel32.BaseThreadInitThunk
00E07741 push eax
00E07742 push 9-34.00E98E50         ;  %d\r\n
00E07747 call 9-34.00E03D14         ;  printf
00E0774C add esp,0x8                ;  调用者堆栈平衡
00E0774F mov eax,[arg.1]            ;  eax = argc
00E07752 sub eax,0x9                ;  eax = eax - 9;argc-9;形式2:变量-常量
00E07755 mov [local.2],eax          ;  nNum = eax
00E07758 mov eax,[local.2]          ;  kernel32.BaseThreadInitThunk
00E0775B push eax
00E0775C push 9-34.00E98E50         ;  %d\r\n
00E07761 call 9-34.00E03D14         ;  printf
00E07766 add esp,0x8
00E07769 mov eax,[local.2]          ;  eax = nNum
00E0776C sub eax,0x1                ;  eax = eax - 1;nNum=nNum-1;形式3:变量-1
00E0776F mov [local.2],eax          ;  nNum = eax
00E07772 mov eax,[local.2]          ;  kernel32.BaseThreadInitThunk
00E07775 push eax
00E07776 push 9-34.00E98E50         ;  %d\r\n
00E0777B call 9-34.00E03D14         ;  printf
00E07780 add esp,0x8
00E07783 xor eax,eax
00E07785 pop edi                    ;  kernel32.74EE38F4
00E07786 pop esi                    ;  kernel32.74EE38F4
00E07787 pop ebx                    ;  kernel32.74EE38F4
00E07788 add esp,0xD8
00E0778E cmp ebp,esp
00E07790 call 9-34.00E02329
00E07795 mov esp,ebp
00E07797 pop ebp                    ;  kernel32.74EE38F4
00E07798 retn

Release反汇编:

012A1260 push ebp
012A1261 mov ebp,esp
012A1263 push esi                      ;9-34.<ModuleEntryPoint>
012A1264 mov esi,[arg.1]               ;esi = nA
012A1267 lea eax,dword ptr ds:[esi-0x8];esi-8;nA-8;形式1:变量-变量
012A126A push eax
012A126B push 9-34.012B64D8            ;%d\r\n
012A1270 call 9-34.printf>;  printf
012A1275 add esi,-0x9                  ;esi = esi-9;argc-9;形式2:变量-常量;-0x9是补码
012A1278 push esi                      ;9-34.<ModuleEntryPoint>
012A1279 push 9-34.012B64D8            ;%d\r\n
012A127E call 9-34.printf>
012A1283 lea eax,dword ptr ds:[esi-0x1];eax = esi-1;nNum-1;形式3:变量-1
012A1286 push eax
012A1287 push 9-34.012B64D8            ;%d\r\n
012A128C call 9-34.printf>
012A1291 add esp,0x18
012A1294 xor eax,eax
012A1296 pop esi                       ;kernel32.74EE38F4
012A1297 pop ebp                       ;kernel32.74EE38F4
012A1298 retn

小结:

1)变量-变量 = lea Reg32,[变量-变量]

2)变量-常量 = add 变量+补码(常量)

3)变量-1 = lea Reg32,[变量-1]

注:这里的代码我和书里不一样,书中是【dec 变量】

0x2 乘法与除法的优化原理

左右移位就相当于在做乘除计算,左移1位相当于乘以2,右移1位相当于除以2。

2.1 乘法

2.1.1 乘法的位移优化

当乘数为2的整数次方、且大于8时,编译器才会使用优化。
c源代码:

int _tmain(int argc, _TCHAR* argv[])
{
	int nNum = 16;
	printf("%p",nNum*argc);

	return 0;
}

Debug汇编

008D7710 push ebp
008D7711 mov ebp,esp
008D7713 sub esp,0xCC
008D7719 push ebx
008D771A push esi                   ;  9-35.<ModuleEntryPoint>
008D771B push edi                   ;  9-35.<ModuleEntryPoint>
008D771C lea edi,[local.51]
008D7722 mov ecx,0x33
008D7727 mov eax,0xCCCCCCCC
008D772C rep stos dword ptr es:[edi]
008D772E mov [local.2],0x10         ;  局部变量nNum = 10;0x10等于十进制16
008D7735 mov eax,[local.2]          ;  eax = 局部变量nNum
008D7738 imul eax,[arg.1]           ;  eax = eax*argc;乘法运算
008D773C push eax
008D773D push 9-35.00968E50         ;  %p
008D7742 call 9-35.008D3D14         ;  printf
008D7747 add esp,0x8
008D774A xor eax,eax
008D774C pop edi                    ;  kernel32.74EE38F4
008D774D pop esi                    ;  kernel32.74EE38F4
008D774E pop ebx                    ;  kernel32.74EE38F4
008D774F add esp,0xCC
008D7755 cmp ebp,esp
008D7757 call 9-35.008D2329
008D775C mov esp,ebp
008D775E pop ebp                    ;  kernel32.74EE38F4
008D775F retn

Release汇编:

000E1260 push ebp
000E1261 mov ebp,esp
000E1263 mov eax,[arg.1]
000E1266 shl eax,0x4  ;  左移动0x4位;左移动乘以4;shl逻辑左移指令[2^4=16]
000E1269 push eax
000E126A push 9-35.000F64D8  ;  %p
000E126F call 9-35.printf>
000E1274 add esp,0x8
000E1277 xor eax,eax
000E1279 pop ebp     ;  kernel32.74EE38F4
000E127A retn

测试:

1)如果结果比2的次方多1会采用加法

2)如果结果比2的次方少1会采用减法

2.1.2 乘法的lea指令优化

C源代码:

int _tmain(int argc, _TCHAR* argv[])
{
	int a = 1, b, c, d, e, f, g;
	b = argc+a*4+6;	// 形式1
	c = argc+a*3+6; // 形式2
	d = argc*2; 	// 形式3
	e = argc*3; 	// 形式4
	f = argc*4; 	// 形式5
	g = argc*11; 	// 形式6
	printf("%d %d %d %d %d %d", b, c, d, e, f, g);

	return 0;
}

Debug汇编:

00DC7710 push ebp
00DC7711 mov ebp,esp
00DC7713 sub esp,0x114
00DC7719 push ebx
00DC771A push esi                            ;  9-36.<ModuleEntryPoint>
00DC771B push edi
00DC771C lea edi,[local.69]
00DC7722 mov ecx,0x45
00DC7727 mov eax,0xCCCCCCCC
00DC772C rep stos dword ptr es:[edi]
00DC772E>mov [local.2],0x1                   ;  给局部变量a赋值
00DC7735 mov eax,[local.2]                   ;  eax = a
00DC7738 mov ecx,[arg.1]                     ;  ecx = argc
00DC773B lea edx,dword ptr ds:[ecx+eax*4+0x6];  edx = argc+a*4+6
00DC773F mov [local.5],edx                   ;  局部变量b = edx
00DC7742 imul eax,[local.2],0x3              ;  先做a*3
00DC7746 mov ecx,[arg.1]                     ;  ecx = argc
00DC7749 lea edx,dword ptr ds:[ecx+eax+0x6]  ;  edx = 【ecx+eax+0x6】;edx = argc + (a*3) + 0x6
00DC774D mov [local.8],edx                   ;  局部变量c = edx
00DC7750 mov eax,[arg.1]                     ;  eax = argc
00DC7753 shl eax,1                           ;  argc*2;左移1位,相当于乘以2
00DC7755 mov [local.11],eax                  ;  赋值给局部变量d
00DC7758 imul eax,[arg.1],0x3                ;  使用乘法指令;argc*3
00DC775C mov [local.14],eax                  ;  局部变量e = eax
00DC775F mov eax,[arg.1]                     ;  eax = argc
00DC7762 shl eax,0x2                         ;  eax = eax*4;左移2位等于乘以4
00DC7765 mov [local.17],eax                  ;  局部变量f = eax
00DC7768 imul eax,[arg.1],0xB                ;  eax = argc*11;B等于十六进制的12
00DC776C mov [local.20],eax                  ;  局部变量g = eax
00DC776F mov eax,[local.20]
00DC7772 push eax
00DC7773 mov ecx,[local.17]
00DC7776 push ecx
00DC7777 mov edx,[local.14]
00DC777A push edx
00DC777B mov eax,[local.11]
00DC777E push eax
00DC777F mov ecx,[local.8]
00DC7782 push ecx
00DC7783 mov edx,[local.5]
00DC7786 push edx
00DC7787 push 9-36.00E58E50                  ;  %d %d %d %d %d %d
00DC778C call 9-36.00DC3D14                  ;  printf
00DC7791 add esp,0x1C
00DC7794 xor eax,eax

Release版反汇编代码:


01271000 push ebp
01271001 mov ebp,esp
01271003 mov ecx,[arg.1]                 ;  exc = argc;argc=1
01271006 imul eax,ecx,0xB                ;  g = argc*11
01271009 push eax
0127100A lea eax,dword ptr ds:[ecx*4]    ;  f = argc*4
01271011 push eax
01271012 lea eax,dword ptr ds:[ecx+ecx*2];  e = argc*3;argc=1+1*2
01271015 push eax
01271016 lea eax,dword ptr ds:[ecx+ecx]  ;  d = argc*2;优化成了加法 1+1
01271019 push eax
0127101A lea eax,dword ptr ds:[ecx+0x9]  ;  c = argc+9; 把a*3+6计算完毕;
0127101D push eax
0127101E lea eax,dword ptr ds:[ecx+0xA]  ;  b = argc+a*4 把a*4+6计算完毕;
01271021 push eax
01271022 push 9-36.01286448              ;  ASCII 25,"d %d %d %d %d %d"
01271027 call 9-36.printf_>
0127102C add esp,0x1C
0127102F xor eax,eax
01271031 pop ebp
01271032 retn 

2.1.3 除法与倒数相乘

编译器世界中倒数相乘的中心思想其实就是用乘法来代替除法运算。它的原理很简单,就是将被除数乘以除数的倒数,其公式为x/y = x*(1/y),我们拿10/2作为例子,我可以得出以下推论:

由 公式x/y = x(1/y) 可得 10/2 = 10(1/2) = 10*0.5

这里没有写反汇编后的状态

2.1.4 倒数相乘与定点运算的配合

理论知识,没仔细去看

除法

2.1.1 除法的识别与优化

这一章虽然讲了编译器对除法的优化,但是不做笔记。

2.2.2 取模运算的识别与优化

不理解,略过,需要用时回头再看

小结

普通除法

mov  Reg32_1,XXXXXXXXh
imul Reg32_2 (被除数)
...
mov  Reg32_1,edx
shr  Reg32_1,1Fh
add  Reg32_1,edx

应用计算结果(如果倒数被向上圆整了,那么根据sar指令后的数值向下圆整即可)如下:

(除数=XXXXXXXXh*2^-32)

除数为2的次方

mov eax,(被除数)
cdq
add edx,XXh
add eax,edx
sar eax,YYh

应用计算结果如下:

(除数 = XXh + 1 或 2^YYh)

标签:nNum,argc,系统安全,esp,mov,eax,push,减法,除法
From: https://blog.csdn.net/ztc131450/article/details/143866834

相关文章

  • HarmonyOS Next智能家居系统安全加固:加解密技术的深度应用
    本文旨在深入探讨华为鸿蒙HarmonyOSNext系统(截止目前API12)在智能家居系统安全加固中加解密技术的应用,基于实际开发经验进行总结。主要作为技术分享与交流载体,难免错漏,欢迎各位同仁提出宝贵意见和问题,以便共同进步。本文为原创内容,任何形式的转载必须注明出处及原作者。一、智......
  • CRM系统安全性排名:数据保护能力评估
    安全性对CRM系统厂商和企业来说至关重要,因为它直接关系到企业的客户数据、商业机密和品牌信誉。CRM系统通常存储了大量敏感信息,包括客户联系详情、交易记录和个人身份信息,一旦发生数据泄露或安全事件,不仅可能导致客户信任丧失、法律诉讼和经济损失,还可能对企业的市场竞争力和长期......
  • springboot毕设高校学生党校信息管理系统安全开发源码+论文+部署
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容一、研究背景随着高校党建工作的不断发展和学生党员队伍的逐步壮大,高校学生党校的管理工作变得日益复杂。传统的人工管理方式已难以满足对众多学生党校相关信......
  • 适应等保的Windows系统和Linux系统安全加固V1.2.0版本
    《Web安全》http://mp.weixin.qq.com/s?__biz=MzkwNjY1Mzc0Nw==&mid=2247484238&idx=1&sn=ca66551c31e37b8d726f151265fc9211&chksm=c0e47a12f793f3049fefde6e9ebe9ec4e2c7626b8594511bd314783719c216bd9929962a71e6&scene=21#wechat_redirect《网安面试指南》http:/......
  • 高精度 加减乘, 除法只提供商
    //bigNum.cpp:此文件包含"main"函数。程序执行将在此处开始并结束。//#include<iostream>#include<cstring>usingnamespacestd;#defineMAXDIGITS100110#definePLUS1#defineMINUS-1typedefstruct{chardigits[MAXDIGITS];......
  • BRICS2024-ST-010-2024一带一路暨金砖国家技能发展与技术创新大赛之企业信息系统安全
    未来技能·创造未来2024一带一路暨金砖国家技能发展与技术创新大赛【企业信息系统安全赛项】BRICS2024-ST-010决赛技术规程金砖国家工商理事会(中方)技能发展工作组一带一路暨金砖国家技能发展与技术创新大赛组会竞赛技术委员会专家组制定2024年4月未来技能·创造未......
  • BRICS2024-ST-010-2024一带一路暨金砖大赛之-企业信息系统安全赛项(选拔赛)技术规程
    未来技能·创造未来2024一带一路暨金砖国家技能发展与技术创新大赛【第二届企业信息系统安全赛项】BRICS2024-ST-010技术规程(选拔赛)金砖国家工商理事会(中方)技能发展工作组一带一路暨金砖国家技能发展与技术创新大赛组会竞赛技术委员会专家组制定2024年4月未来技能......
  • 系统安全第十次作业题目及答案
    一、1.机密性完整性可用性可控性隐私性2.存储介质处理对象管理系统3.数据库管理软件4.库内加密库外加密5.潜在违规分析基于异常检测的描述简单攻击试探法复杂攻击试探法二、1.B2.ACDE3.ABCDE4.ABCEF三、1.答:(1)对数据库加密对原有系统功能的影响不......
  • 系统安全第九次作业题目及答案
    一、1.A1B3B2B1C2C1D12.主令牌模拟令牌3.自主访问控制列表系统访问控制列表二、1.ABC2.A3.ABCD4.ABD5.AB三、1.答:在Windows操作系统中,事件的审核类型可以分为两类:成功事件和失败事件。它们对于系统被攻击的追踪非常有用,即使是成功的审核事件,它也只是表......
  • 20-数据库系统安全
    20.1概况1)概念数据库安全是指数据库的机密性、完整性、可用性能够得到保障,其主要涉及数据库管理安全、数据安全、数据库应用安全以及数据库运行安全。2)威胁授权的误用逻辑推断和汇聚:利用逻辑推理,把不太敏感的数据结合起来可以推断出敏感信息。进行逻辑推断也可能要用到某些......