【CTF大赛】第五届XMan选拔赛 ezCM Writeup

本文介绍了第五届XMan选拔赛中的ezCM题目,该题目涉及Golang程序分析,重点是椭圆曲线算法(ECC)。作者详细讲述了如何通过分析程序验证方式来构造KeyFile,包括程序的前置知识、关键函数定位、KeyFile格式解析、验证逻辑等步骤,最终成功注册并获取flag。文章还分享了在Golang逆向和ECC算法学习过程中的心得。
摘要由CSDN通过智能技术生成

ezCM

直至比赛结束,这道题目都是 0 解题,一方面是因为比赛时间较短,另一方面还是因为这道题目较难,考察了不常见的椭圆曲线算法(ECC),大大增加了对做题者的要求。

题目信息

在这里插入图片描述
题目是使用 Golang 来编写的一个 CrackMe 程序,程序内符号没有被去除,所以这篇文章就不会讲解如何恢复 Golang 程序符号,另外 IDA Pro 7.6 已经支持 Golang 程序分析,打开就可以直接恢复被去除的符号信息。

题目要求打开一个 KeyFile ,并且通过读取其文件的内容来注册程序,我们要做的就是通过分析程序验证方式来编写一个 KeyFile,使其可以通过程序注册验证,最终拿到 flag 数据。

前置知识

由于是 Golang 的题目,在一些数据结构和调用约定上和大多数语言都不一样,所以一定不能过于的依赖伪代码,在调试过程中最好能够多关注汇编代码,这样在逆向过程中会快速掌握到核心。这部分内容参考学习了 panda0s – Golang underlying data representaion ,本来是不想把这部分内容放在这篇文章中的,但是由于关联性过大,所以不得不拿来饱满文章内容。
函数调用

在函数调用的过程中,无论是调用参数还是返回值都是通过栈来传递。
在这里插入图片描述
其传参的特征是

  1. 参数传递顺序是从右往左传递,而且不使用像是 push pop 这样的操作栈的指令,而是直接对栈上的内容进行修改。
  2. 参数传递一般都是借助一个寄存器中转,例如
    rax、rcx,先把数据原来的储存位置的数据赋值到这个寄存器上,然后再把这个寄存器的内容赋值给栈上数据,并且如果数据是 0x10
    size 的结构体,就会借助 xmm 寄存器中转来加速。

其返回值的特征是

  1. 返回值的位置紧贴着在最后一个参数的地址之后。以上图为例,最后一个参数的地址是 rsp + 0x250 – 0x248 + 0x8 =
    rsp + 0x10,所以这里的返回值的地址就是在 rsp + 0x250 – 0x238 = rsp +
    0x18,有多个返回值的情况也是类似。

方法调用

在上图中,严格意义上并不是一次函数调用,而是一次方法调用。他是对 MyMainWindow 这个对象下的 Academy 方法进行了调用,这个传入的参数就是这个对象的指针,像是 this 一样。这个对象的指针就相对于函数调用的第一个参数。

String 字符串
在这里插入图片描述
String 结构

struct String{
   
    char * strPtr;
    int64 size;
}

所以 Golang 程序在传递字符串的时候,同时也会在后续跟一个参数,这个参数指的就是字符串的长度。同时由于这样的机制,使得字符串的内容在内存中分布不需要截止符’\x00’
在这里插入图片描述
Slice 切片

在其他语言中(例如 python),Slice 是一种切片的操作,切片之后可以返回一个新的数据对象,但是 Golang 中的 Slice 不仅仅是一种切片的操作,更像是一种灵活的数据结构。

了解 Slice 结构后,在 IDA 中修改对应的变量类型,可以大大加快分析速度。

Slice 结构

struct slice {
   
    dq    Pointer;
    dq    Length;
    dq    Capacity;
}

Pointer:指向 Slice 底层数组的元素开始位置的指针

Length:Slice 的当前长度

Capacity:Slice 底层数组的最大长度,超过此长度会自动扩展
初始化 Slice

my_slice := make([]int, 35)

这表示先声明一个长度为 5、数据类型为 int 的底层数组,然后从这个底层数组中从前向后取 3 个元素作为 slice 的结构(length = 3,cap = 5)

make 最底层调用 runtime_makeslice 分配空间,这个函数返回的是指向内部数组的指针
访问 Slice

org_len := slice1[name_size + 1]

在这里插入图片描述
在访问 Slice 中元素时,会检测是否越界如果越界则调用 runtime_panicIndex

append / copy

当 Length 已经等于 Capacity 的时候,再使用 append 给 slice 追加元素,会调用 runtime_growslice 进行扩容。

在代码中的表现是在 append / copy 的时候会检测,slice.len + 1 与 slice1.cap 的大小关系
在这里插入图片描述
如图在把 slice 转换为字符串的过程前,由于将要 copy slice,所以会对传参 len 进行检测。

切片截取

myvar 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值