跟羽夏学 Ghidra ——数据
写在前面
此系列是本人一个字一个字码出来的,包括示例和实验截图。本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正。 如有好的建议,欢迎反馈。码字不易,如果本篇文章有帮助你的,如有闲钱,可以打赏支持我的创作。如想转载,请把我的转载信息附在文章后面,并声明我的个人信息和本人博客地址即可,但必须事先通知我。
你如果是从中间插过来看的,请仔细阅读 跟羽夏学 Ghidra ——简述 ,方便学习本教程。请认准 博客园 的 寂静的羽夏 ,目前仅在## 写在前面
此系列是本人一个字一个字码出来的,包括示例和实验截图。本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正。 如有好的建议,欢迎反馈。码字不易,如果本篇文章有帮助你的,如有闲钱,可以打赏支持我的创作。如想转载,请把我的转载信息附在文章后面,并声明我的个人信息和本人博客地址即可,但必须事先通知我。
你如果是从中间插过来看的,请仔细阅读 跟羽夏学 Ghidra ——简述 ,方便学习本教程。请认准 博客园 的 寂静的羽夏 ,目前仅在该平台发布。## 写在前面
此系列是本人一个字一个字码出来的,包括示例和实验截图。本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正。 如有好的建议,欢迎反馈。码字不易,如果本篇文章有帮助你的,如有闲钱,可以打赏支持我的创作。如想转载,请把我的转载信息附在文章后面,并声明我的个人信息和本人博客地址即可,但必须事先通知我。
你如果是从中间插过来看的,请仔细阅读 跟羽夏学 Ghidra ——简述 ,方便学习本教程。请认准 博客园 的 寂静的羽夏 ,目前仅在该平台发布。
前言
本篇涉及一些底层的知识,主要是变量在内存的分配情况。如果不清楚,可以参考我的 羽夏看C语言系列教程 。虽然是Win平台的,但相差无几,原理相通。
在开始之前,一定要将代码编译好(其实上一篇就开始用了),这次我们要开始用示例进行学习工作。注意在简述说的基础知识都一定要会,不过我用的时候会提一下。
本篇寂静的羽夏的博文,将专注于variable函数的分析,紧扣“数据”关键词。
函数定位
我们从分析variable函数开始,讲解与数据相关的知识,首先需要定位。那么如何定位呢?
通过上一篇博文的学习,我们知道了需要从Symbol Tree就能找到,双击就能跳转到函数位置:

与此同时,我们可以看到反汇编的内容:
void variable(void)
{
gvar1 = 0x31;
gvar2 = 5;
puts("===");
puts("===");
gvar2 = 5;
gstruct[0] = 1;
gstruct._2_2_ = 2;
gstruct._4_4_ = 3;
gstruct._8_8_ = 4;
gvar1 = 0x50;
return;
}
和我们的源码作比较:
// Written by WingSummer
void variable()
{
//局部变量
gvar1 = '1';
gvar2 = 5;
puts("===");
struct tstruct lstruct;
lstruct.var1 = 1;
lstruct.var2 = 2;
lstruct.var3 = 3;
lstruct.var4 = 4;
// 全局变量赋值
puts("===");
gvar1 = 'P';
gvar2 = 5;
gstruct.var1 = 1;
gstruct.var2 = 2;
gstruct.var3 = 3;
gstruct.var4 = 4;
}
可以看出,类型对不上,局部变量的结构体相关赋值被吃掉了。但是,Ghidra已经在反汇编结果中有了提示:
undefined AL:1 <RETURN>
undefined8 Stack[-0x10]:8 local_10 XREF[1]: 00401196(W)
undefined4 Stack[-0x14]:4 local_14 XREF[1]: 0040118f(W)
undefined2 Stack[-0x16]:2 local_16 XREF[1]: 00401189(W)
undefined1 Stack[-0x18]:1 local_18 XREF[1]: 00401185(W)
Ghidra已经识别到了局部变量,但是,并没有使用,反汇编并没有将其列入。不过,我们先把反汇编的变量名和源代码的名字弄的一致。有如下三种方法:
- 在符号树列表:

- 在反编译窗口:

- 在反汇编窗口:

你可以使用以上方式来修改。
在我们的源代码中gvar1 = '1',在反汇编就成了gvar1 = 0x31,这个是由于反汇编是使用的ASCII表示的字符1,我们有两种方式进行转化:
- 在反编译窗口:

- 在反汇编窗口:

与此同时,我们在程序中用到了大量的结构体,但是Ghidra并没有完全给识别出来,那么怎么创建呢:

在Data Type Manager中,选中tutorial(因为我的程序的名字叫这个),右击菜单的New,然后找到Structure,点击,最终的编辑结果:

在这里注意的一点是,结构体是四个字节对齐的,至于为什么自己回去复习功课。
我们编辑完毕后,点击保存按钮,那么我们如何使用我们自定义类型呢:

点击后,搜索找到我们的类型,点击确定,最终会得到下面的结果:
void variable(void)
{
tstruct lstruct;
gvar1 = '1';
gvar2 = 5;
puts("===");
puts("===");
gvar2 = 5;
gstruct.var1 = 1;
gstruct.var2 = 2;
gstruct.var3 = 3;
gstruct.var4 = 4;
gvar1 = 'P';
return;
}
至此,创建结构体的方式学会了,我们就可以创建枚举、别名、共用体。这些我就不在本篇赘述了,请自行触类旁通。
回到主函数
下面我们回到主函数,继续学习如何更改函数签名以及修正原是字符串的未知类型。
主函数的反编译结果如下:
undefined8 main(void)
{
int iVar1;
int local_14;
uint local_10;
char local_9;
while( true ) {
while( true ) {
while( true ) {
while( true ) {
puts(&DAT_004020d8);
__isoc99_scanf(&DAT_0040218c,&local_14);
if (local_14 != 2) break;
loop();
}
if (2 < local_14) break;
if (local_14 != 1) goto LAB_0040146a;
variable();
}
if (local_14 != 3) break;
test1();
puts("===");
test2(1);
puts("===");
local_9 = test3(5,0x41);
printf("ret : %c",(ulong)(uint)(int)local_9);
puts("===");
local_10 = test4(1,2,3,4,5,6);
printf("ret : %d",(ulong)local_10);
}
if (local_14 != 4) break;
iVar1 = crackMe();
if (iVar1 == 0) {
puts(&DAT_004021c0);
}
else {
puts(&DAT_004021a1);
}
setbuf(stdin,(char *)0x0);
}
LAB_0040146a:
puts(&DAT_004021e8);
getchar();
return 0;
}
首先我们修改一下主函数的函数声明,也就是函数签名(有三种方式):
- 在符号树列表:

- 在反编译窗口:

- 在反汇编窗口:

点击会弹出一个窗体,我们修改一下如下图所示:

可以看到,通过该对话框可以修改函数名、返回值、调用约定以及函数属性(不定参数、内敛函数、无返回值),更改参数,这些可以自行探索。
接下来我们看到puts(&DAT_004020d8)这样的代码,这明明是字符串,但并没有识别到,仅仅被认为是普通数据。我们可以通过修改识别为ASCII字符串:

修改后,是如下结果:
s__Ghidra_0._1._2._3._4._004020d8 XREF[2]: main:0040132d(*),
main:0040132d(*)
004020d8 e6 ac ds E6h,ACh,A2h,E8h,BFh,8Eh,E6h,9Dh,A5h,
a2 e8
bf 8e
但是这完全没有正常字符串的样子,这个是编码问题。在 Linux 下,中文的编码通常是UTF-8,我们需要修改一下:

点击后,就会弹出一下弹窗,修改如下:

最终,我们的结果如下(由于字符串太长,被隐掉了):
s__Ghidra_0._1._2._3._4._004020d8 XREF[2]: main:0040132d(*),
main:0040132d(*)
004020d8 e6 ac ds u8"欢迎来到“寂静的羽夏”的 Ghidra 教学教程
a2 e8
bf 8e
拓展
在本寂静的羽夏的实验示例中,我们还没有涉及数组以及如果将代码识别为数据或者把数据是别为代码,这怎样处理,下面开始介绍。
由于没有提前设计,我们假设variable函数中的gvar2是一个数组,长度是5,那么我们如何转化呢?

在gvar2的位置右击,找到Data,选中Create Array,你将会得到如下界面:

输入数字即可,由于它不是,就不用点确定了。
下面我们取消之前的假设,我们做一个新的,假设variable函数开头的一句汇编是数据,其实不是代码,我们如何将其转为数据呢?
我们先把代码转为数据:

点击后,该处汇编将会变成未定义类型的字节。但我反悔了,我又想把它弄成数据(不要撤销):

右键菜单通常比较麻烦,这里只是为了介绍才这么做,通常用C和D这两个快捷键,对代码和数据之间进行转化。
其次,我还没有介绍如何更改类型,只是说了如何使用自己定义的类型。下面看一下:

点击后,会弹出一个对话框,输入正确的类型名字即可。
至此,该博文结束。
下一篇
跟羽夏学 Ghidra ——引用
跟羽夏学 Ghidra ——数据的更多相关文章
- 跟羽夏学 Ghidra ——窗口
写在前面 此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇文章 ...
- 跟羽夏学 Ghidra ——工具
写在前面 此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇文章 ...
- 跟羽夏学 Ghidra ——引用
写在前面 此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇文章 ...
- 跟羽夏学 Ghidra ——导航
写在前面 此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇文章 ...
- 跟羽夏学 Ghidra ——初识
写在前面 此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇文章 ...
- 跟羽夏学 Ghidra ——调试
写在前面 此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇文章 ...
- (二)羽夏看C语言——容器
写在前面 由于此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇 ...
- 羽夏 Bash 简明教程(上)
写在前面 该文章根据 the unix workbench 中的 Bash Programming 进行汉化处理并作出自己的整理,并参考 Bash 脚本教程 和 BashPitfalls 相关内容 ...
- 羽夏看Linux内核——启动那些事
写在前面 此系列是本人一个字一个字码出来的,包括示例和实验截图.如有好的建议,欢迎反馈.码字不易,如果本篇文章有帮助你的,如有闲钱,可以打赏支持我的创作.如想转载,请把我的转载信息附在文章后面,并 ...
随机推荐
- 使用navicat连接远程linux mysql数据库出现10061
重启mysql服务 两种方式 1.使用 service 启动:service mysql restart 2.使用 mysqld 脚本启动:/etc/inint.d/mysql restart
- Day04 HTML标记
路径 ./ 同级目录 ./ 进入该目录名下 ../ 上一级目录 HTML标记 图片 <!-- 图片标记 src 图片的路径 width 设置图片宽度 height 设置图片高度 title 鼠标 ...
- Java开发学习(七)----DI依赖注入之自动装配与集合注入
一.自动配置 上一篇博客花了大量的时间把Spring的注入去学习了下,总结起来就两个字麻烦.麻烦在配置文件的编写配置上.那有更简单方式么?有,自动配置 1.1 依赖自动装配 IoC容器根据bean所依 ...
- 写出个灵活的系统竟然可以如此简单!小白也能写出高级的Java业务!
一 最近正好公司里有个需求,一个短信业务接了多个第三方供应商,某些业务需要查询第三方供应商剩余的短信包数量去选择剩余量最多的渠道去批量发送.有些业务是指定了某个短信供应商,有些场景需要根据业务的值去动 ...
- 集合-List接口常用实现类的对比
1.collection接口:单列集合,用来存储一个一个的对象 2. list接口:存储有序的.可重复的数据. --->"动态数组",替换原有的数组 (1) Arraylis ...
- C#金额数字转换中文繁体
/// <summary> /// 数字转换中文繁体金钱 /// </summary> /// <param name="Digital">&l ...
- GET 请求和 POST 请求的区别和使用
作为前端开发, HTTP 中的 POST 请求和 GET 请求是经常会用到的东西,有的人可能知道,但对其原理和如何使用并不特别清楚,那么今天来浅谈一下两者的区别与如何使用. GET请求和POST请求的 ...
- 基于mpvue的框架开发微信小程序(搭建环境)
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_103 美团很早就开源了mpvue这个项目,如此看来,美团可不仅仅是一家团购网站,真正的技术驱动型企业,使得我们多了一种用来开发微信 ...
- 使用python3.7配置开发钉钉群自定义机器人(2020年新版攻略)
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_132 最近疫情比较严重,很多公司依靠阿里旗下的办公软件钉钉来进行远程办公,当然了,钉钉这个产品真的是让人一言难尽,要多难用有多难用 ...
- C# 从补码中获取有符号数的实际数值
C# 从补码中获取有符号数的实际数值 原理 计算机存储数据时,默认是存储数据的补码.有符号的数粗存在符号位(最高位). 这里就会提到原码.反码.补码的概念. 原码:用符号位和数值表示带符号数,正数的符 ...