一个简单的C程序反汇编解析.
- 格式:doc
- 大小:23.50 KB
- 文档页数:10
C语言中的安全性代码防篡改与反编译保护C语言作为一种广泛应用的编程语言,拥有强大的功能和灵活性。
然而,C语言编写的代码很容易受到恶意篡改和反编译的攻击。
为了保护代码的安全性,开发人员需要采取一些措施来防止代码的篡改和反编译。
本文将介绍C语言中常用的安全性代码防篡改与反编译保护方法。
一、常见的安全性代码防篡改方法1. 常量加密常量加密是一种常见的防止代码被篡改的方法。
在使用常量的地方,可以将常量进行加密处理,使得攻击者无法直接读取和修改常量的值。
常量加密可以通过对常量进行异或运算或者加密算法等方式来实现。
在程序运行时,需要对加密的常量进行解密,然后使用解密后的常量进行计算和操作。
2. 代码混淆代码混淆是一种将代码转换成难以理解和分析的形式的方法。
通过对代码进行重写,删除无用代码,添加冗余代码等操作,可以使代码的结构和逻辑变得复杂。
代码混淆可以增加攻击者对代码的理解和分析难度,从而提高代码的安全性。
常见的代码混淆技术包括函数内联、循环展开、代码重组等。
3. 授权验证授权验证是一种通过验证机制来保护代码安全的方法。
在代码中添加授权验证模块,用来验证代码的合法性和授权信息。
通过对授权信息进行加密处理,可以防止攻击者对授权信息的篡改和伪造。
授权验证可以通过校验码、数字签名等方式来实现,有效防止未授权的使用和修改。
二、反编译保护方法1. 逆向难度提升逆向难度提升是一种增加反编译难度的方法。
通过在代码中使用一些反调试、反跟踪和混淆技术,可以增加攻击者对代码的分析和理解难度,从而提高反编译的难度。
常见的逆向难度提升技术包括函数内联、指令替换、代码流程混淆等。
2. 加密保护加密保护是一种将代码和数据进行加密处理的方法。
通过对代码和数据进行加密,可以有效防止攻击者对代码的分析和修改。
在程序运行时,需要对加密的代码和数据进行解密,然后再进行执行和操作。
常见的加密保护技术包括代码加密、数据加密、混淆等。
3. 指令混淆指令混淆是一种将指令顺序、结构和操作进行重排和混淆的方法。
简单的汇编程序分析汇编程序1将这段程序保存为hello.s ,然后⽤汇编器as 把汇编程序中的助记符翻译成机器指令(汇编指令与机器指令是对应的)⽣成⽬标⽂件hello.o 。
然后⽤链接器ld 把⽬标⽂件hello.o 链接成可执⾏⽂件hello (虽然只有⼀个⽬标⽂件但是也需要经过链接才能成为可执⾏⽂件因为链接器要修改⽬标⽂件中的⼀些信息)。
这个程序只做了⼀件事就是退出,退出状态为4。
shell 中可以echo $?得到上⼀条命令的退出状态。
汇编程序中以"."开头的名称不是指令的助记符,不会被翻译成机器指令,⽽是给汇编器⼀些特殊的指⽰,称为汇编指⽰或伪操作。
.section 指⽰把代码划分成若⼲个段(section),程序被操作系统加载时,每个段被加载到不同的地址,具有不同的读写执⾏权限。
.data 段保存程序的数据是可读写的,C 程序的全局变量也属于.data 段。
上边的程序没定义数据所以.data 是空的。
.text 段保存代码,是只读和可执⾏的,后⾯那些指令都属于这个.text 段。
_start 是⼀个符号(Symbol),符号在汇编程序中代表⼀个地址,可以⽤在指令中,汇编程序经过汇编器的处理后所有的符号都被替换成它所代表的地址值。
在C 中我们可以通过变量名访问⼀个变量,其实就是读写某个地址的内存单元,我们通过函数名调⽤⼀个函数其实就是调转到该函数的第⼀条指令所在的地址,所以变量名和函数名都是符号,本质上是代表内存地址的。
.globl 指⽰告诉汇编器_start 这个符号要被链接器⽤到,所以要在⽬标⽂件的符号表中给它特殊标记。
_start 就像C 程序的main 函数⼀样特殊是整个程序的⼊⼝,链接器在链接时会查找⽬标⽂件中的_start 符号代表的地址,把它设置为整个程序的⼊⼝地址,所以每个汇编程序都要提供⼀个_start 符号并且⽤.globl 声明。
如果⼀个符号没有⽤.globl 指⽰声明这个符号就不会被链接器⽤到。
反编译初识⼀. 反编译(反汇编)简介 1.1. 为什么要反编译(汇编 assembly 反汇编 dissembly) 1.1.1. 反编译原因如下: a. 逆向破解程序,作为⼀个有逼格,素养的我肯定不会这么⼲的。
哈哈 b. 调试程序时,反汇编代码可以帮助我们理解程序(我们学习时使⽤objdump主要⽬的是这个),尤其是在理解链接脚本、链接地址等概念时 c. 把C语⾔源代码编译链接⽣成的可执⾏程序反汇编后得到对应的汇编代码,可以帮助我们理解C语⾔和汇编语⾔之间的对应关系。
⾮常有助于深⼊理解C语⾔。
1.2. 反编译命令 1.2.1. arm-linux-objdump -D led.elf > led_elf.dis 命令 a. objdump是gcc⼯具链中的反汇编⼯具,作⽤是由编译链接好的elf格式的可执⾏程序反过来得到汇编源代码 b. -D表⽰反汇编 1.2.1. 获得反编译⽂件过程 a. 此过程是基于上篇⽂章《》,前期准备参考此⽂章 b. 反编译后⽣成led_elf.disroot@ubuntu:/mnt/hgfs/windows_share/baseC/lesson1.4.13-LED# lsled.S Makefile mkv210_image.c write2sd 说明.txtroot@ubuntu:/mnt/hgfs/windows_share/baseC/lesson1.4.13-LED# makearm-linux-gcc -o led.o led.S -carm-linux-ld -Ttext 0x0 -o led.elf led.oarm-linux-objcopy -O binary led.elf led.binarm-linux-objdump -D led.elf > led_elf.disgcc mkv210_image.c -o mkx210./mkx210 led.bin 210.binroot@ubuntu:/mnt/hgfs/windows_share/baseC/lesson1.4.13-LED# ls210.bin led.elf led.o Makefile mkx210 说明.txtled.bin led_elf.dis led.S mkv210_image.c write2sdroot@ubuntu:/mnt/hgfs/windows_share/baseC/lesson1.4.13-LED#View Code 1.3. 反编译⽂件led_elf.dis分析 1.3.1. 我们选取⼀段分析 00000000 <_start>:0: e59f1060 ldr r1, [pc, #96] ; 68 <delay_loop+0x10> a. 00000000 <_start>: 表⽰标号地址、标号名字 b. 0: e59f1060表⽰指令地址、指令机器码 c. ldr r1, [pc, #96]表⽰指令机器码反汇编到的指令,由于有流⽔线的存在,此时PC值是当初指令地址+9; d. 68 <delay_loop+0x10>表⽰注释;0x68 = 96+8led.elf: file format elf32-littlearmDisassembly of section .text:00000000 <_start>:0: e59f1060 ldr r1, [pc, #96] ; 68 <delay_loop+0x10>4: e59f0060 ldr r0, [pc, #96] ; 6c <delay_loop+0x14>8: e5810000 str r0, [r1]0000000c <while>:c: e59f105c ldr r1, [pc, #92] ; 70 <delay_loop+0x18>10: e3e00008 mvn r0, #814: e5810000 str r0, [r1]18: eb00000c bl 50 <delay>1c: e59f104c ldr r1, [pc, #76] ; 70 <delay_loop+0x18> 20: e3e00010 mvn r0, #1624: e5810000 str r0, [r1]28: eb000008 bl 50 <delay>2c: e59f103c ldr r1, [pc, #60] ; 70 <delay_loop+0x18> 30: e3e00020 mvn r0, #3234: e5810000 str r0, [r1]38: eb000004 bl 50 <delay>3c: e59f102c ldr r1, [pc, #44] ; 70 <delay_loop+0x18> 40: e3e00010 mvn r0, #1644: e5810000 str r0, [r1]48: eb000000 bl 50 <delay>4c: eaffffee b c <while>00000050 <delay>:50: e59f201c ldr r2, [pc, #28] ; 74 <delay_loop+0x1c> 54: e3a03000 mov r3, #000000058 <delay_loop>:58: e2422001 sub r2, r2, #15c: e1520003 cmp r2, r360: 1afffffc bne 58 <delay_loop>64: e1a0f00e mov pc, lr68: e0200240 eor r0, r0, r0, asr #46c: 00111000 andseq r1, r1, r070: e0200244 eor r0, r0, r4, asr #474: 00895440 addeq r5, r9, r0, asr #8Disassembly of section .ARM.attributes:00000000 <.ARM.attributes>:0: 00001a41 andeq r1, r0, r1, asr #204: 61656100 cmnvs r5, r0, lsl #28: 01006962 tsteq r0, r2, ror #18c: 00000010 andeq r0, r0, r0, lsl r010: 45543505 ldrbmi r3, [r4, #-1285] ; 0x50514: 08040600 stmdaeq r4, {r9, sl}18: Address 0x00000018is out of bounds.View Code参考《朱⽼师.1.2ARM裸机课件》。
Linux下简单C语⾔⼩程序的反汇编分析韩洋原创作品转载请注明出处《Linux内核分析》MOOC课程写在开始,本⽂为因为参加MOOC相关课程⽽写的作业,如有疏漏,还请指出。
选了⼀门Linux内核分析课程,因为阅读内核代码中或多或少要涉及到At&T汇编代码的阅读,所以这⾥写下⼀个对⼀个简单C命令⾏程序的反汇编分析过程,⼀⽅⾯完成作业,另⼀⽅⾯当作练⼿。
下⾯开始:1、编写我们的C语⾔⼩程序这⾥我们使⽤简单的例⼦,代码如下:1 #include <stdio.h>23int exG(int x)4 {5return x + 5;6 }78int exF(int x)9 {10return exG(x);11 }1213int main(void)14 {15return exF(10) + 2;16 }使⽤vim等编辑器写⼊上述代码,保存到main.c,然后使⽤下⾯命令⽣成汇编源⽂件:x86系统:$gcc -S -o main.s main.cx64系统:$gcc -m32 -S -o main.s main.c因为我们这⾥以32位平台为例⼦,所以在x64机器上要加上-m32来使GCC⽣成32位的汇编源⽂件。
2、处理源⽂件执⾏完上述命令后,当前⽬录下就会有⼀个main.s的⽂件,使⽤vim打开,不需要的链接信息[以"."开头的⾏],得到如下汇编代码:1 exG:2 pushl %ebp3 movl %esp, %ebp4 movl 8(%ebp), %eax5 addl $5, %eax6 popl %ebp7 ret8 exF:9 pushl %ebp10 movl %esp, %ebp11 pushl 8(%ebp)12 call exG13 addl $4, %esp14 leave15 ret16 main:17 pushl %ebp18 movl %esp, %ebp19 pushl $1020 call exF21 addl $4, %esp22 addl $2, %eax23 leave24 ret可以看到这个⽂件⾥是GCC帮我们⽣成的汇编代码,这⾥需要说明下AT&T格式和intel格式,这两种格式GCC是都可以⽣成的,如果要⽣成intel格式的汇编代码,只需要加上 -masm=intel选项即可,但是Linux下默认是使⽤AT&T格式来书写汇编代码,Linux Kernel代码中也是AT&T格式,我们要慢慢习惯使⽤AT&T格式书写汇编代码。
c语言位顺序反
在C语言中,可以使用位运算符来实现位顺序反转。
具体来说,可以使用异或运算符(^)和左移运算符(<<)来实现。
以下是一个示例代码,演示如何使用位运算符实现位顺序反转:
```c
include <>
int reverseBits(int num) {
int result = 0;
int i;
for (i = 0; i < 32; i++) {
result = result ^ (num << i);
}
return result;
}
int main() {
int num = 0x;
int reversed = reverseBits(num);
printf("原数:0x%X\n", num);
printf("反转后:0x%X\n", reversed);
return 0;
}
```
在上面的代码中,reverseBits函数接受一个整数num作为输入,并返回其位顺序反转后的结果。
该函数使用一个循环来迭代32次,每次将num左移一位并与result进行异或运算,最终得到反转后的结果。
在主函数中,我们定义了一个整数num,并将其传递给reverseBits函数进行位顺序反转。
然后,我们打印出原数和反转后的结果。
需要注意的是,上述代码中的位顺序反转是指将整数的二进制表示中的位顺序进行反转。
例如,如果num的二进制表示为,则其位顺序反转后的结果为。
C语言逆向工程与反汇编技术解析C语言逆向工程与反汇编技术是现代计算机科学领域中的重要研究方向,它们具有广泛的应用和深远的影响。
本文将对C语言逆向工程与反汇编技术进行深入解析,介绍其原理、方法和应用。
一、C语言逆向工程的原理与方法1.1 C语言逆向工程的概念C语言逆向工程是指通过分析、理解和修改C语言代码,以了解程序的内部结构、运行机制和逻辑设计的一种技术。
它可以帮助开发人员深入了解程序的实现细节,并从中获取有用的信息,如算法、数据结构、API调用等。
1.2 C语言逆向工程的方法C语言逆向工程主要使用反汇编、调试和静态分析等方法进行。
其中,反汇编是将程序的二进制代码转换为汇编代码的过程,通过分析汇编代码,可以还原出程序的逻辑结构和运行轨迹。
调试是指通过运行程序,并在运行过程中观察和分析程序的行为,从而了解其内部机制和变量的具体取值。
静态分析是在不运行程序的情况下,直接对程序的源代码或二进制代码进行分析,以推测程序的行为和逻辑。
二、反汇编技术的原理与应用2.1 反汇编的原理反汇编是将机器码翻译成汇编指令的过程。
在计算机中,指令是由一系列二进制位组成的。
反汇编程序通过解析这些二进制位,识别出对应的指令,并将其翻译为汇编指令,以便开发人员阅读和理解。
2.2 反汇编技术的应用反汇编技术广泛应用于软件逆向工程、安全分析和漏洞挖掘等领域。
通过反汇编,可以还原出程序的源代码或类似源代码的结构,进而分析程序的逻辑和功能。
此外,反汇编技术还可以用于恶意代码分析、密码破解和软件修改等方面,提供了重要的技术支持。
三、C语言逆向工程与反汇编技术的应用案例3.1 软件安全分析使用C语言逆向工程与反汇编技术,可以对软件进行安全漏洞分析。
通过对程序进行反汇编,分析程序的执行流程和函数调用关系,可以发现潜在的漏洞和安全隐患,并采取相应的修复措施,提高软件的安全性。
3.2 软件破解与修改逆向工程与反汇编技术常常被用于软件破解和修改。
——啊冲第四节C语言判断与分支的反汇编If else语句•int myfunction(int c)•{•if (c>0 && c<10)•{•printf("c>0 \n");•}•else if (c>10 && c<100)•{•printf("c>10 && c<100 \n");•}•else•{•printf("其它\n");•}•return c;•}If判断都是使用cmp再加上条件跳转指令。
对于if(a && b)的情况,一般都是使用否决法。
如果a不成立,立刻跳到走,如果b不成立,同样跳走。
从这里看出,在用C语言写一系列条件比较的时候,应该注意排列这些比较,让比较次数越少越好。
cmp<条件>,<初始值>jle <下一个分支>else if和else的特点是,在开始的地方,都有一条无条件跳转指令,跳转到判断结束处,阻止前面的分支执行结束后,直接进入这个分支的可能。
这个分支能执行到的唯一途径是前面的判断条件不满足。
Else 则在jmp之后直接执行操作。
而else if则开始重复if之后的操作,用cmp比较,然后用条件跳转指令进行跳转。
Swtich case语句条件分支中,有比较特殊的情况是switch.switch 的特点是有多个判断.因为swtich 显然不用判断大于小于,所以都是je,分别跳到每个case处。
最后一个是无条件跳转,直接跳到default 处。
•switch(c)•{•case 0:•printf("c=0");•case 1:•{•printf("c=1");•break;•}•default:•printf("C是其它数");•}连续的比较与跳转让人想到switchCmp …Je ….Cmp …Je ……Jmp …至于case 和default 都非常简单.如果有break,则会增加一个无条件跳转.没有break 的情况下,没有任何循环控制代码.反汇编练习:把汇编代码还原成C语言。
VS2008反汇编小解了解反汇编的一些小知识对于我们在开发软件时进行编程与调试大有好处,下面以VS2008环境下的VC++简单介绍一下反汇编的一些小东西!如果有些解释有问题的地方,希望大家能够指出。
1、新建简单的VC控制台应用程序(对此熟悉的同学可以略过)A、打开Microsoft Visual Studio 2008,选择主菜单“File”B、选择子菜单“New”下面的“Project”,打开“New Project”对话框。
C、左边选择Visual C++下的win32,右边选择Win32 Console Application,然后输入一个工程名,点击“OK”即可,在出现的向导中,一切默认,点击Finish即可。
D、在出现的编辑区域内会出现以你设定的工程名命名的CPP文件。
内容如下:#include "stdafx.h"int _tmain(int argc, _TCHAR* argv[]){return 0;}2、VS查看汇编代码A、VC处于调试状态才能看到汇编指令窗口。
因此,可以在return 0 上设置一个断点:把光标移到return0 那一行上,然后按下F9键设置一个断点。
B、按下F5键进入调试状态,当程序停在return 0 这一行上时,打开菜单“Debug”下的“Windows”子菜单,选择“Disassembly”。
这样,出现一个反汇编的窗口,显示下面的信息:--- d:\my documents\visual studio 2008\projects\casmtest\casmtest\casmtest_main.cpp// CAsmTest.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"int _tmain(int argc, _TCHAR* argv[]){00411370 push ebp00411371 mov ebp,esp00411373 sub esp,0C0h00411379 push ebx0041137A push esi0041137B push edi0041137C lea edi,[ebp-0C0h]00411382 mov ecx,30h00411387 mov eax,0CCCCCCCCh0041138C rep stos dword ptr es:[edi]return 0;0041138E xor eax,eax}00411390 pop edi00411391 pop esi00411392 pop ebx00411393 mov esp,ebp00411395 pop ebp00411396 ret上面就是系统生成的main函数原型,确切的说是_tmain()的反汇编的相关信息,相信学过汇编语言的肯定就能够了解它所做的操作了。
使⽤gcc命令把C语⾔程序反汇编之前看过⼀点汇编,不过现在都忘记得差不多了。
最近⼜很蛋疼地想起反汇编这个东西。
这⾥使⽤ gcc 命令对 .c ⽂件进⾏反汇编,把 C语⾔翻译成汇编语⾔先准备⼀个简单的 C 程序sum.c#include <stdio.h>int add(int, int);int mode(int, int);int main(){int a = 3, b = 2;int s = add(3, 2);int m = mode(3, 2);return0;}int add(int a, int b){return a + b;}int mode(int a, int b){return a % b;}在控制台中先进到保存 sum.c 的⽂件夹下,当然你也可以⽤绝对路径,使⽤以下命令gcc -S sum.c -o sum_at.s这个命令默认⽣成的是 AT&T 汇编,⽣成的 sum_at.s 如下.file "sum.c".text.def ___main; .scl 2; .type 32; .endef.globl _main.def _main; .scl 2; .type 32; .endef_main:LFB13:.cfi_startprocpushl %ebp.cfi_def_cfa_offset 8.cfi_offset 5, -8movl %esp, %ebp.cfi_def_cfa_register 5andl $-16, %espsubl $32, %espcall ___mainmovl $3, 28(%esp)movl $2, 24(%esp)movl $2, 4(%esp)movl $3, (%esp)call _addmovl %eax, 20(%esp)movl $2, 4(%esp)movl $3, (%esp)call _modemovl %eax, 16(%esp)movl $0, %eaxleave.cfi_restore 5.cfi_def_cfa 4, 4ret.cfi_endprocLFE13:.globl _add.def _add; .scl 2; .type 32; .endef_add:LFB14:.cfi_startprocpushl %ebp.cfi_def_cfa_offset 8.cfi_offset 5, -8movl %esp, %ebp.cfi_def_cfa_register 5movl 8(%ebp), %edxmovl 12(%ebp), %eaxaddl %edx, %eaxpopl %ebp.cfi_restore 5.cfi_def_cfa 4, 4ret.cfi_endprocLFE14:.globl _mode.def _mode; .scl 2; .type 32; .endef_mode:LFB15:.cfi_startprocpushl %ebp.cfi_def_cfa_offset 8.cfi_offset 5, -8movl %esp, %ebp.cfi_def_cfa_register 5movl 8(%ebp), %eaxcltdidivl 12(%ebp)movl %edx, %eaxpopl %ebp.cfi_restore 5.cfi_def_cfa 4, 4ret.cfi_endprocLFE15:.ident "GCC: (i686-posix-dwarf-rev0, Built by MinGW-W64 project) 7.3.0"我之前看的是intel汇编也就是8086这种 intel 芯⽚,要转成 intel 汇编使⽤以下命令gcc -S -masm=intel sum.c -o sum_intel.s⽣成的 sum_intel.s ⽂件内容如下.file "sum.c".intel_syntax noprefix.text.def ___main; .scl 2; .type 32; .endef.globl _main.def _main; .scl 2; .type 32; .endef_main:LFB13:.cfi_startprocpush ebp.cfi_def_cfa_offset 8.cfi_offset 5, -8mov ebp, esp.cfi_def_cfa_register 5and esp, -16sub esp, 32call ___mainmov DWORD PTR [esp+28], 3mov DWORD PTR [esp+24], 2mov DWORD PTR [esp+4], 2mov DWORD PTR [esp], 3call _addmov DWORD PTR [esp+20], eaxmov DWORD PTR [esp+4], 2mov DWORD PTR [esp], 3call _modemov DWORD PTR [esp+16], eaxmov eax, 0leave.cfi_restore 5.cfi_def_cfa 4, 4ret.cfi_endprocLFE13:.globl _add.def _add; .scl 2; .type 32; .endef_add:LFB14:.cfi_startprocpush ebp.cfi_def_cfa_offset 8.cfi_offset 5, -8mov ebp, esp.cfi_def_cfa_register 5mov edx, DWORD PTR [ebp+8]mov eax, DWORD PTR [ebp+12]add eax, edxpop ebp.cfi_restore 5.cfi_def_cfa 4, 4ret.cfi_endprocLFE14:.globl _mode.def _mode; .scl 2; .type 32; .endef_mode:LFB15:.cfi_startprocpush ebp.cfi_def_cfa_offset 8.cfi_offset 5, -8mov ebp, esp.cfi_def_cfa_register 5mov eax, DWORD PTR [ebp+8]cdqidiv DWORD PTR [ebp+12]mov eax, edxpop ebp.cfi_restore 5.cfi_def_cfa 4, 4ret.cfi_endprocLFE15:.ident "GCC: (i686-posix-dwarf-rev0, Built by MinGW-W64 project) 7.3.0"等我复习下汇编再回来看这段代码到底⼲了什么。