您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

反编译入门

时间:2023-01-14 15:20:36  来源:今日头条  作者:嵌入式实验楼

我们在写单片机裸机程序时,在主函数之前,会有一段启动代码,而启动代码是用汇编写的,有些朋友可能看到汇编头都大了,当时要想深入研究底层架构,这快硬骨头就必须去啃。

汇编:汇编文件转换为目标文件(里面是机器码)。

反汇编:可执行文件(目标文件,里面是机器码),转换为汇编文件。

关于汇编的基础知识,请看笔者以前的文章。

今天笔者以stm32F1的点灯程序为例,带领大家进行反汇编,并阅读反汇编后的代码。

1 新建LED裸机程序

关于STM32裸机程序的创建,请看笔者博文:

https://bruceou.blog.csdn.NET/article/detAIls/78244735

但是今天这个程序非常简单,不应那么复杂。

1.新建文件夹

新建文件夹“STM32F1”,当然名字也可以另取,在 STM32F1文件夹下,我们新建五个文件夹,分别为CMSIS、Listing、Output、Project、User。


 

其中CMSIS文件夹放启动文件:


 

笔者的开发板芯片是STM32F103ZE,这个文件是根据STM32的固件库startup_stm32f10x_md.s文件修改而来。

2.新建工程

打开Keil,在工具栏 Project->New μVision Project…新建我们的工程文件。


 

输入工程名,保存即可。


 

窗口是让我们选择公司跟芯片的型号,我们用的芯片是 ST 公司的STM32F103ZE,有64K SRAM,512K Flash,属于高集成度的芯片。按如下选择即可。


 

然后点击项目管理。


 

最后修改后的内容如下:


 

并添加相应的文件。


 

其中main.c的内容如下所示:

* @brief 延时函数* @param d* @retval Nonevoid delay(int d)while(d--);* @brief main* @param None* @retval intint main(void)unsigned int *pReg;/* 使能GPIOB */pReg = (unsigned int *)(0x40021000 + 0x18);*pReg |= (1<<3);/* 设置GPIOB0为输出引脚 */pReg = (unsigned int *)(0x40010C00 + 0x00);*pReg |= (1<<0);pReg = (unsigned int *)(0x40010C00 + 0x0C);while (1)/* 设置GPIOB0输出1 */*pReg |= (1<<0);delay(1000000);/* 设置GPIOB0输出0 */*pReg &= ~(1<<0);delay(1000000);

startup.s文件的内容如下:

;************************************ STM32F1 ************************************;* File Name : startup.s;* Author : BruceOu;* Version : V1.0;* Date : 2021-06-27;* Description : STM32F10x Medium Density Devices Vector table for MDK-ARM;* toolchain.;* This module performs:;* - Set the initial SP;* - Set the initial PC == Reset_Handler;* - Set the vector table entries with the exceptions ISR address;* - Configure the clock system;* - Branches to __main in the C library (which eventually;* calls main()).;* After Reset the CortexM3 processor is in Thread mode,;* priority is Privileged, and the Stack is set to Main.PRESERVE8THUMB; Vector Table MApped to Address 0 at ResetAREA RESET, DATA, READONLYEXPORT __Vectors__Vectors DCD 0DCD Reset_Handler ; Reset HandlerAREA |.text|, CODE, READONLY; Reset handlerReset_Handler PROCEXPORT Reset_Handler [WEAK]IMPORT mainLDR SP, =(0x20000000+0x10000)BL mainENDP

接下来还有配置工程。


 

选择Output文件夹。


 

选择Listing文件夹。


 

基本配置就这些,接下来编译工程。


 

只要没有错误就可以了,最后就是下载程序,笔者使用的是J-Link,最后的现象如下:


 

LED会不停闪烁。

2 Keil反汇编

接下来才是今天正题,反汇编。

在KEIL的User选项中,如下图添加这两项:

fromelf --bin --output=STM32F1.bin ../Output/STM32F1.axffromelf --text -a -c --output=STM32F1.dis ../Output/STM32F1.axf

然后重新编译,即可得到二进制文件STM32F1.bin(以后会分析)、反汇编文件STM32F1.dis。

如下图所示:


 

正常编译过程是分为四个阶段进行的,即预处理(也称预编译,Preprocessing)、编译(Compilation)、汇编 (Assembly)和链接(Linking)。

但是反编译是讲为二进制文件反编译成汇编文件,因此反汇编的流程如下:


 

3反汇编代码解析

接下来就是查看反编译代码,打开反编译文件Project/STM32F1.dis。这里只截取一段查看,因为格式都是一样的,知识每条内容不同罢了。


 

第一列是链接地址,第二列是机器码,第三列是汇编指令。

根本汇编指令,我们找到ARM®v7-M Architecture Reference Manual_DDI 0403E.d (ID070218)中的LDR指令。


 

我们将F8DFD004变成二进制。


 

这个使用的32位的Thumb2指令集。


 

其中b0~b11是立即数,这里是4,对应的汇编代码的也是4,这里要注意的是,ARM指令采用流水线机制,当前执行地址A的指令,同时已经在对下一条指令进行译码同时已经在读取下下一条指令:PC = A +4 (Thumb/Thumb2指令集)。


 

B12~b15是寄存器,这段大小是0XC,对应的寄存器就是sp;


 

后面16bit除了23位意外,全是固定的,其中‘U’表示无条件执行,这里置为1。

其他的汇编指令对应的机器码也是类似的,值得注意的是,不同的架构对应的机器码也是不同的,这也就回答了为了不同的处理器架构会对应不同的指令集。

有兴趣的可以对比Cortex-M系列和Cortex-A系列的的指令集。请参考以下手册:

ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition.pdf

ARM®v7-M Architecture Reference Manual.pdf

4反汇编代码全解析

进入debug模式,在View下选择disassembly window。


 

这样就可将机器码和对应的代码对应起来。当程序运行起来了,也就从异常向量表中跳转到Reset_Handler中,然后跳转到main函数中,而main函数是在栈中,因此需要设置占空间的起始位置。根据STM32的参考手册,SRAM的其起始地址和大小如下:


 

因此栈顶为起始位置加上栈的大小即可,只要不超过SRAM即可。


 

值得注意的是,栈是向低地址扩展的数据结构,是一块连续的内存区域,栈顶的地址和栈的最大容量是在通过LDR设置,因此需要根据应用需求合理分配栈空间。

接下来往下走,如果在汇编中不打断点,会默认进入main函数的一条指令,就从这里分析。为了分析方便,这里还有使用上一节方便出来的文件。


 


 

【C代码33行】

从内存地址0x0800 017c拷贝数据0x40021018到r3中,也就是

r3 = * 0x0800 017c

也就是将pReg指针保存到r3中。


 

【C代码34行】

这里对应3条指令


 

首先将r3拷贝到r0中,然后将r0或上1左移3位,也就是

ORR r0,r0,#8

最后将r0的值写入r3所指地址中。

【C代码37行】

同33行,从内存地址0x0800 0180拷贝数据40010c00到r3中


 

【C代码38行】

同34行,这里也对应3条指令:


 

【C代码40行】

和33行不同的是,这里分了两条指令:


 

笔者认为前面是编译器优化了。根据ARM指令采用流水线机制,当前执行地址A的指令,同时已经在对下一条指令进行译码同时已经在读取下下一条指令:PC = A +4 (Thumb/Thumb2指令集)。因此前面类似的代码被优化了。

接下来就进入循环中。


 

后面就移植在死循环中,不断操作GPIO的亮灭。

【C代码45行】

这里是将B0设置为1,和34行类似。


 

【C代码47行】

这里将进入延时函数。


 

进入延时函数:


 

NOP是字节对齐,减少指令的内存访问次数。首先将变量d保存到r0,然后将r0赋给r1,接着是r0自减1,紧接着是r1与0比较,如果r1等于0,则会返回,否则,又从头开始,值得注意的是,这里先比较,然后r0才自减的。

为了进一步说明,可以看--d的汇编代码。


 

这里就是相当于r1先减1,然后再比较的。

【C代码50行】

这行代码对应一下指令,很简单。


 

5总结

在前面使用Keil进行了反汇编,也对相应的C代码进行了分析。我们看到的反汇编代码如下:


 

根据反汇编的代码,可将其对应到Flash,在Flash上的内容如下表所示:

地址

Flash内容

0x08000000

0x08000004

0x08000008

f8dfd004

0x0800000c

f000f80c

最后总结下点灯的流程:

第一步:设置栈:CPU会从0x08000000读取值,用来设置SP。

第二步:跳转:CPU从0x08000004得到地址值,根据它的BIT0切换为ARM状态或Thumb状态,然后跳转。

第三步:对于cortex M3/M4,它只支持Thumb状态,所以0x08000004上的值bit0必定是1,0x08000004上的值 = Reset_Handler + 1。从Reset_Handler继续执行。

第四步:然后进入到主函数中执行相应C代码



Tags:反编译   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
这两个强大的开源C#反编译逆向工具,探索C#桌面应用的秘密
C#的应用也比较多,有时候,我们想要研究一下别人的优秀的项目,可能会借助一些非常规手段来学习。下面,我就分享几款开源的C#反编译工具。dnSpydnSpy 是一个用C#开发,开源的调试器...【详细内容】
2023-03-30  Search: 反编译  点击:(330)  评论:(0)  加入收藏
为啥用IDEA反编译没有擦除泛型?
有些擦除了但有些没有擦除泛型类型,到底该信谁呢?当然是无条件相信​​javap -c​​,因为一切反编译操作都基于它。so结论是:Java的泛型是伪泛型,编译后泛型类型都会被擦除。...【详细内容】
2023-03-06  Search: 反编译  点击:(151)  评论:(0)  加入收藏
Android逆向之旅—反编译利器Apktool使用教程
一、下载软件首先下载apktool.bat和apktool.jar 官网地址:https://ibotpeaches.github.io/Apktool/install/ 这个译文: 1.下载Windows包装脚本(右键单击,将链接另存为apktool....【详细内容】
2023-03-02  Search: 反编译  点击:(214)  评论:(0)  加入收藏
反编译入门
我们在写单片机裸机程序时,在主函数之前,会有一段启动代码,而启动代码是用汇编写的,有些朋友可能看到汇编头都大了,当时要想深入研究底层架构,这快硬骨头就必须去啃。汇编:汇编文件...【详细内容】
2023-01-14  Search: 反编译  点击:(222)  评论:(0)  加入收藏
保护小程序,防止反编译:打造不怕反编译的小程序
这几年,小程序、小游戏,非常火。业内人都知道,小程序或小游戏,就是H5应用,就是html+JS。这类应用,反编译很容易,网上就有很多方法教程。对小程序反编译之后,可轻松获得源码。稍加修...【详细内容】
2022-12-30  Search: 反编译  点击:(431)  评论:(0)  加入收藏
SpringBoot 玩一玩代码混淆,防止反编译代码泄露
编译简单就是把代码跑一哈,然后我们的代码 .java文件 就被编译成了 .class 文件反编译就是针对编译生成的 jar/war 包 里面的 .class 文件 逆向还原回来,可以看到你的代码写的...【详细内容】
2022-11-20  Search: 反编译  点击:(564)  评论:(0)  加入收藏
如何防止你的 jar 包被反编译?
Java作为解释型的语言,其高度抽象的特性意味其很容易被反编译,容易被反编译,自然有防止反编译措施存在。今天就拜读了一篇相关的文章,受益匪浅,知彼知己嘛!!之所以会对java的反编译...【详细内容】
2022-08-30  Search: 反编译  点击:(442)  评论:(0)  加入收藏
防止jar被反编译——最简单的方法
有的时候,给别人提供的jar,有些核心的密匙不想被人通过反编译工具查看,那么要怎样才能做到呢?既要能正常调用,又不想别人反编译jar查看源码网上有很多方法,有使用第三方工具的、使...【详细内容】
2022-08-18  Search: 反编译  点击:(584)  评论:(0)  加入收藏
最流行的 .NET 反编译工具合集
编译和反编译.NET 中的编译是把开发人员写的 C# 代码转化为计算机可理解的代码的过程,也就是中间语言代码(IL代码)。在这个过程中,C# 源代码被转换为可执行文件(exe或者dll 文件)...【详细内容】
2022-07-15  Search: 反编译  点击:(561)  评论:(0)  加入收藏
python反编译和防破解
python是一种解释型语言,但是与javascript这种纯脚本语言不同,python提供了一种编译成字节码运行的方法,编译之后就得到pyc文件,这点和java编译成class文件再用jvm解释运行很类...【详细内容】
2022-05-09  Search: 反编译  点击:(555)  评论:(0)  加入收藏
▌简易百科推荐
Netflix 是如何管理 2.38 亿会员的
作者 | Surabhi Diwan译者 | 明知山策划 | TinaNetflix 高级软件工程师 Surabhi Diwan 在 2023 年旧金山 QCon 大会上发表了题为管理 Netflix 的 2.38 亿会员 的演讲。她在...【详细内容】
2024-04-08    InfoQ  Tags:Netflix   点击:(3)  评论:(0)  加入收藏
即将过时的 5 种软件开发技能!
作者 | Eran Yahav编译 | 言征出品 | 51CTO技术栈(微信号:blog51cto) 时至今日,AI编码工具已经进化到足够强大了吗?这未必好回答,但从2023 年 Stack Overflow 上的调查数据来看,44%...【详细内容】
2024-04-03    51CTO  Tags:软件开发   点击:(8)  评论:(0)  加入收藏
跳转链接代码怎么写?
在网页开发中,跳转链接是一项常见的功能。然而,对于非技术人员来说,编写跳转链接代码可能会显得有些困难。不用担心!我们可以借助外链平台来简化操作,即使没有编程经验,也能轻松实...【详细内容】
2024-03-27  蓝色天纪    Tags:跳转链接   点击:(15)  评论:(0)  加入收藏
中台亡了,问题到底出在哪里?
曾几何时,中台一度被当做“变革灵药”,嫁接在“前台作战单元”和“后台资源部门”之间,实现企业各业务线的“打通”和全域业务能力集成,提高开发和服务效率。但在中台如火如荼之...【详细内容】
2024-03-27  dbaplus社群    Tags:中台   点击:(11)  评论:(0)  加入收藏
员工写了个比删库更可怕的Bug!
想必大家都听说过删库跑路吧,我之前一直把它当一个段子来看。可万万没想到,就在昨天,我们公司的某位员工,竟然写了一个比删库更可怕的 Bug!给大家分享一下(不是公开处刑),希望朋友们...【详细内容】
2024-03-26  dbaplus社群    Tags:Bug   点击:(8)  评论:(0)  加入收藏
我们一起聊聊什么是正向代理和反向代理
从字面意思上看,代理就是代替处理的意思,一个对象有能力代替另一个对象处理某一件事。代理,这个词在我们的日常生活中也不陌生,比如在购物、旅游等场景中,我们经常会委托别人代替...【详细内容】
2024-03-26  萤火架构  微信公众号  Tags:正向代理   点击:(14)  评论:(0)  加入收藏
看一遍就理解:IO模型详解
前言大家好,我是程序员田螺。今天我们一起来学习IO模型。在本文开始前呢,先问问大家几个问题哈~什么是IO呢?什么是阻塞非阻塞IO?什么是同步异步IO?什么是IO多路复用?select/epoll...【详细内容】
2024-03-26  捡田螺的小男孩  微信公众号  Tags:IO模型   点击:(10)  评论:(0)  加入收藏
为什么都说 HashMap 是线程不安全的?
做Java开发的人,应该都用过 HashMap 这种集合。今天就和大家来聊聊,为什么 HashMap 是线程不安全的。1.HashMap 数据结构简单来说,HashMap 基于哈希表实现。它使用键的哈希码来...【详细内容】
2024-03-22  Java技术指北  微信公众号  Tags:HashMap   点击:(12)  评论:(0)  加入收藏
如何从头开始编写LoRA代码,这有一份教程
选自 lightning.ai作者:Sebastian Raschka机器之心编译编辑:陈萍作者表示:在各种有效的 LLM 微调方法中,LoRA 仍然是他的首选。LoRA(Low-Rank Adaptation)作为一种用于微调 LLM(大...【详细内容】
2024-03-21  机器之心Pro    Tags:LoRA   点击:(13)  评论:(0)  加入收藏
这样搭建日志中心,传统的ELK就扔了吧!
最近客户有个新需求,就是想查看网站的访问情况。由于网站没有做google的统计和百度的统计,所以访问情况,只能通过日志查看,通过脚本的形式给客户导出也不太实际,给客户写个简单的...【详细内容】
2024-03-20  dbaplus社群    Tags:日志   点击:(6)  评论:(0)  加入收藏
站内最新
站内热门
站内头条