写在前面

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

你如果是从中间插过来看的,请仔细阅读 跟羽夏学 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读写多个sheet文件

    前言 怎么样使用Python提高自己的工作效率,今天就给大家分享这个吧. 我们经常用pandas读入读写excel文件,经常会遇到一个excel文件里存在多个sheet文件,这个时候,就需要一次性读取 ...

  2. JavaScript进阶内容——jQuery

    JavaScript进阶内容--jQuery 我们在前面的文章中已经掌握了JavaScript的全部内容,现在让我们了解一下JavaScript库 这篇文章主要是为了为大家大致讲解JavaScript ...

  3. elastsearch整合springboot

    文档地址: https://www.baeldung.com/elasticsearch-java

  4. 算法竞赛进阶指南0x41并查集

    并查集简介 并查集的两类操作: Get 查询任意一个元素是属于哪一个集合. Merge 把两个集合合并在一起. 基本思想:找到代表元. 注意有两种方法: 使用一个固定的值(查询方便,但是在合并的时候需 ...

  5. Junit使用步骤和junit_@Before&@After

    测试: 1.定义一个测试类(测试用例) 建议: 测试类名:被测试的类型Test CalculatorTest 包名:xxx.xxx.xx.test com.li.Test 2.定义测试方法:可以独立运 ...

  6. 丽泽普及2022交流赛day21 社论

    A 暴力 . greater<double> -> greater<int> \(100\) -> \(50\) 代码丢了 . B dp . 考场上代码抢救一下就过 ...

  7. 如何有效管理产品生命周期(How to Effectively Manage a Product Lifecycle)

    本文翻译自文章:How to Effectively Manage a Product Lifecycle 文章原文链接:https://medium.com/design-bootcamp/how- ...

  8. 软件装在D盘,实测有效

    C盘容量小,希望把所有软件都装到D盘,试过很多次,没什么作用.今天装MS全家桶的时候看到了个帖子,实测有效,Visio.Word.Excel.PowerPoint都装到了D盘 原贴链接为:http:/ ...

  9. Redis 01 概述

    参考源 https://www.bilibili.com/video/BV1S54y1R7SB?spm_id_from=333.999.0.0 版本 本文章基于 Redis 6.2.6 简介 NoSQ ...

  10. Go语言 context包源码学习

    你必须非常努力,才能看起来毫不费力! 微信搜索公众号[ 漫漫Coding路 ],一起From Zero To Hero ! 前言 日常 Go 开发中,Context 包是用的最多的一个了,几乎所有函数 ...