[MRCTF2020]hello

[MRCTF2020]hello,第1张

buuctf做题记录

查壳


64位无壳

IDA反编译

F5了main_main函数,看函数列表的时候就觉得不对劲,之后查了查这道题似乎是GO语言写的,属于是新的知识点。

函数很乱,对GO语言没有了解,所以在判断语句周围点出数据查看,找到明文flag。(按’a’转换成字符串形式)

小记

GO语言了解甚少,如果不是这种明文flag感觉很难找到函数逻辑,查资料时找到了一个叫IDAGolangHelper的插件,不过不是很会用,学习内容+1.
(IDA似乎给了个GO1.13,可能因为插件没有这个版本才没用?)

GO语言

IDAGolangHelper下载

Go 语言二进制文件有它自己的特殊性:

Go 语言内置一些复杂的数据类型,并支持类型的组合与方法绑定,这些复杂数据类型在汇编层面有独特的表示方式和用法。比如 Go 二进制文件中的 string 数据不是传统的以 0x00 结尾的 C-String,而是用 (StartAddress, Length) 两个元素表示一个 string 数据;比如一个 slice 数据要由 (StartAddress, Length, Capacity) 三个元素表示。这样的话,在汇编代码中看,给一个函数传一个 string 类型的参数,其实要传两个值;给一个函数传一个 slice 类型的参数,其实要传 3 个值。返回值同理;独特的调用约定和栈管理机制,使 C/C++ 二进制文件逆向分析的经验在这里力不从心:Go 语言用的是 continue stack 栈管理机制 ,并且 Go 语言函数中callee 的栈空间由 caller 来维护,callee 的参数、返回值都由 caller 在栈中预留空间,就难以直观看出哪个是参数、哪个是返回值。详见 The Go low-level calling convention on x86-64 ;全静态链接构建,里面函数的数量动辄大几千,如果没有调试信息和符号,想静态逆向分析其中的特定功能点,如大海捞针,很容易迷失在函数的海洋中;动态调试难度更大,其独特的 Goroutine 调度机制再加上海量的函数,很容易调飞。 连续栈

Go语言支持goroutine,每个goroutine需要能够运行,所以它们都有自己的栈。假如每个goroutine分配固定栈大小并且不能增长,太小则会导致溢出,太大又会浪费空间,无法存在许多的goroutine。

为了解决这个问题,goroutine可以初始时只给栈分配很小的空间,然后随着使用过程中的需要自动地增长。这就是为什么Go可以开千千万万个goroutine而不会耗尽内存。

Go1.3版本之后则使用的是continuous stack。

每次执行函数调用时Go的runtime都会进行检测,若当前栈的大小不够用,则会触发“中断”,从当前函数进入到Go的运行时库,Go的运行时库会保存此时的函数上下文环境,然后分配一个新的足够大的栈空间,将旧栈的内容拷贝到新栈中,并做一些设置,使得当函数恢复运行时,函数会在新分配的栈中继续执行,仿佛整个过程都没发生过一样,这个函数会觉得自己使用的是一块大小“无限”的栈空间。

Go语言逆向基础
连续栈

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/990891.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存