跟羽夏学 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内核——启动那些事
写在前面 此系列是本人一个字一个字码出来的,包括示例和实验截图.如有好的建议,欢迎反馈.码字不易,如果本篇文章有帮助你的,如有闲钱,可以打赏支持我的创作.如想转载,请把我的转载信息附在文章后面,并 ...
随机推荐
- 从零开始实现lmax-Disruptor队列(四)多线程生产者MultiProducerSequencer原理解析
MyDisruptor V4版本介绍 在v3版本的MyDisruptor实现多线程消费者后.按照计划,v4版本的MyDisruptor需要支持线程安全的多线程生产者功能. 由于该文属于系列博客的一部分 ...
- java通过注解指定顺序导入excel
自定义的属性,用来判断顺序的 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; impor ...
- APISpace 未来7天生活指数API接口 免费好用
随着经济的发展,我们的生活水平在不断的提高,生活指数在我们的生活中也越来越受到关注,根据当天的生活指数,我们就可以知道在今天我们可以干什么比较好. 未来7天生活指数API,支持国内3400+个城市 ...
- HBase学习(二) 基本命令 Java api
一.Hbase shell 1.Region信息观察 创建表指定命名空间 在创建表的时候可以选择创建到bigdata17这个namespace中,如何实现呢? 使用这种格式即可:'命名空间名称:表名' ...
- Centos7较为彻底的删除mysql
Centos7下较为彻底的删除mysql(root 身份操作) 删除mysql安装包 1. yum检查 yum list installed | grep mysql 安装则直接删除 示例:yum r ...
- Nginx第三方模块Ngx-dyups安装过程
Ngx-dyups是什么,能干什么 它是一个Nginx第三方动态Upstream配置模块,可以实现在不重启Nginx情况下动态更新反向代理Upstream表.该模块由淘宝开发团队维护,淘宝自家的Ten ...
- AtCoder Beginner Contest 260 E // 双指针 + 差分
题目传送门:E - At Least One (atcoder.jp) 题意: 给定大小为N的两个数组A,B,求长度分别为1~M的满足以下条件的连续序列数量,条件为: 对于每个i(从1~N),Ai和B ...
- 标准的Switch语句和穿透的Switch语句
第三章 选择语句 3.1选择语句--Switch switch语句格式: ```java switch(表达式){ case 常量值1: 语句体1; break; case 常量值2: 语句体2; b ...
- Javaweb-JSP详解
一.什么是JSP Java Server Pages:Java服务器端页面,和Servlet一样,用于动态web技术 最大的特点: 写JSP就像在写HTML 区别: HTML只给用户提供静态的数据 J ...
- Minimax 社论
目录 题面 题解 代码 Reference 题面 LOJ #2537 / 洛谷 P5298 「PKUWC2018」Minimax 一棵有根二叉树 \(\mathcal T\) . 定义结点 \(x\) ...