写在前面

  此系列是本人一个字一个字码出来的,包括示例和实验截图。本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正。 如有好的建议,欢迎反馈。码字不易,如果本篇文章有帮助你的,如有闲钱,可以打赏支持我的创作。如想转载,请把我的转载信息附在文章后面,并声明我的个人信息和本人博客地址即可,但必须事先通知我

你如果是从中间插过来看的,请仔细阅读 跟羽夏学 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函数开头的一句汇编是数据,其实不是代码,我们如何将其转为数据呢?

  我们先把代码转为数据:

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

  右键菜单通常比较麻烦,这里只是为了介绍才这么做,通常用CD这两个快捷键,对代码和数据之间进行转化。

  其次,我还没有介绍如何更改类型,只是说了如何使用自己定义的类型。下面看一下:

  点击后,会弹出一个对话框,输入正确的类型名字即可。

  至此,该博文结束。

下一篇

  跟羽夏学 Ghidra ——引用

跟羽夏学 Ghidra ——数据的更多相关文章

  1. 跟羽夏学 Ghidra ——窗口

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇文章 ...

  2. 跟羽夏学 Ghidra ——工具

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇文章 ...

  3. 跟羽夏学 Ghidra ——引用

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇文章 ...

  4. 跟羽夏学 Ghidra ——导航

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇文章 ...

  5. 跟羽夏学 Ghidra ——初识

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇文章 ...

  6. 跟羽夏学 Ghidra ——调试

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇文章 ...

  7. (二)羽夏看C语言——容器

    写在前面   由于此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇 ...

  8. 羽夏 Bash 简明教程(上)

    写在前面   该文章根据 the unix workbench 中的 Bash Programming 进行汉化处理并作出自己的整理,并参考 Bash 脚本教程 和 BashPitfalls 相关内容 ...

  9. 羽夏看Linux内核——启动那些事

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.如有好的建议,欢迎反馈.码字不易,如果本篇文章有帮助你的,如有闲钱,可以打赏支持我的创作.如想转载,请把我的转载信息附在文章后面,并 ...

随机推荐

  1. python——进行年龄和性别检测

    年龄和性别检测 使用Python编程语言带你完成使用机器学习进行年龄和性别检测的任务. 首先需要编写用于检测人脸的代码,因为如果没有人脸检测,我们将无法进一步完成年龄和性别预测的任务. 下一步是预测图 ...

  2. SQL优化常用的几种方法

    为什么要对SQL优化: 1.执行性能低 2.等待时间过长 3.SQL写的太差 4.索引失效 ·····等等 SQL优化的一些方法: 1.EXPLAIN 做MySQL优化,我们要善用EXPLAIN查看S ...

  3. REST 表现层状态转化

    1.REST是什么? 1) REST:即 Representational State Transfer.(资源)表现层状态转化.是目前最流行的一种互联网软件架构.它结构清晰.符合标准.易于理解.扩展 ...

  4. jdk8 hashmap 链表resize 源码分析

    重点看这部分代码 for (int j = 0; j < oldCap; ++j) { Node<K,V> e; if ((e = oldTab[j]) != null) { old ...

  5. Java中运算符和方法的区别

    1.多数情况下,运算符是程序语言里固有的.比如+,-,*,/.可以直接被编译为机器语言而无需再调用其它方法编译. 2.运算符在被定义时会被规定运算的优先级.如4+3*3,会得到13.而不是21. 3. ...

  6. 第2章 开始学习C++

    说明 看<C++ Primer Plus>时整理的学习笔记,部分内容完全摘抄自<C++ Primer Plus>(第6版)中文版,Stephen Prata 著,张海龙 袁国忠 ...

  7. 2022徐特立科学营&BIT机器人队电控课程讲义

    目录 \(\cdot\)电控简介 \(\cdot\)认识单片机   什么是单片机   时钟-单片机的脉搏 \(\cdot\)外设及应用   GPIO   PWM   定时器   UART \(\cdo ...

  8. React报错之组件不能作为JSX组件使用

    正文从这开始~ 总览 组件不能作为JSX组件使用,出现该错误有多个原因: 返回JSX元素数组,而不是单个元素. 从组件中返回JSX元素或者null以外的任何值. 使用过时的React类型声明. 返回单 ...

  9. GreatSQL季报(2021.12.26)

    欢迎来到 GreatSQL社区分享的MySQL技术文章,如有疑问或想学习的内容,可以在下方评论区留言,看到后会进行解答 自从GreatSQL 8.0.25 于 2021.8.26发布以来,针对MGR的 ...

  10. Geometrics类定义

    首先我的结构图是这样的,当然你自己喜欢怎么改都行.这个不影响,只要包含到正确的头文件就行. geometrics是几何类的基础,所有几何的碰撞都是从这个类继承下来的.书中也说的很清楚了,大家可以阅读对 ...