我让 AI 来帮我写文章、分析代码,甚至参加了 CTF 夺旗比赛!
2022-12-2808:00
CertiK
2022-12-28 08:00
CertiK
2022-12-28 08:00
收藏文章
订阅专栏

近期,CertiK 参加了 Aptos CTF MOVEment 2022比赛。

与所有夺旗(CTF)比赛一样,参赛团队主要面临的挑战就是如何快速理解和总结复杂代码片断语义

这次,CertiK 团队决定通过 ChatGPT(一个由 OpenAI 训练的大型语言模型)来解决这一问题。

ChatGPT 最近以其强大的信息整合和对话能力惊艳了全球,在自然语言处理上面表现出了惊人的能力。这次的夺旗比赛,也让我们看到了它理解和解释用各种编程语言编写的代码方面所具备的价值。

本文将为大家分享我们在此次 CTF MOVEment 2022 比赛中运用 ChatGPT 的经验,并讨论在 CTF 比赛中使用这一工具的优势。


ChatGPT 相关基础代码操作

我们可以向ChatGPT提出关于代码的问题,并得到清晰而简洁的答案,这可以帮助我们迅速掌握代码的功能,在 CTF 竞赛中节省宝贵的时间。

例如,当看到用 Move 编写的代码片段时,ChatGPT 能够提供代码的语义摘要,并以简单的自然语言解释代码的作用。当我们在 CTF 比赛中试图快速理解代码时,这可以为我们节省大量的时间和精力。

例①:总结代码的功能

下方这一例子,可说明 ChatGPT 如何总结 CTF 竞赛中提供代码片段的功能。
public fun pow(g: u128, x: u128, p: u128): u128 {  let ans = 1;    g = g % p;    while (x !=0) {      if((x & 1) == 1) {        ans = ((ans % p) * (g % p)) % p;      };      x = x >> 1;      g = (g * g) % p。    };    ans  }

ChatGPT 的回答:该代码定义了一个名为pow的公共函数,该函数接收三个参数:gxp。该函数计算gx次幂(模数p)的模幂运算结果,它通过使用循环重复对g求平方,并在x的最低有效位为1时将其乘以ans来实现,然后返回结果。总的来说,这段代码提供了一种方法来计算g的模块化指数到x次方,模数为p

我们对使用 ChatGPT 获得的结果印象非常深刻。尽管代码不是特别长,但在 ChatGPT 的帮助下,理解和总结起来要比直接阅读代码快得多。

这说明了 ChatGPT 可以在一定程度上帮助到那些没有太多经验的工程师。通过使用 ChatGPT,他们可以迅速了解代码的概况理解其目的和结构,这可以节省大量的时间和精力。


ChatGPT 相关进阶代码操作

尽管 MOVE 是一种相对较新的语言,ChatGPT 还是能够提供相应有用的信息。我们决定通过一个稍高级的程序来进一步测试其能力。这里是另一个示例,ChatGPT 可以帮助解释导致运行时失败的极端情况,并帮助我们在代码测试期间进行调试。

例②:查找一个潜在的运行时错误

提问:下方的代码在哪些情况下会执行失败?   
    fun encrypt_string(plaintext : vector<u8>) : vector<u8> {        let key : vector<u8> = transaction_context::get_script_hash();        let key_len : u64 = vector::length(&key);
let ciphertext : vector<u8> = vector::empty<u8>();
let i = 0; while ( i < vector::length(&plaintext) ) { vector::push_back(&mut ciphertext, *vector::borrow(&plaintext, i) ^ *vector::borrow(&key, (i % key_len))); i = i + 1; }; ciphertext }

ChatGPT 的回答:如果transaction_context::get_script_hash()返回一个空向量,或者在传入明文或密钥时vector::length()返回0,问题中的代码可能无法执行。在这两种情况下,代码中的 while 循环都不会执行,该函数只会返回一个空向量

虽然 ChatGPT 可能无法确定异常的确切位置,但它仍然可以提供有用的见解和对极端案例和潜在问题的描述。在这种情况下,ChatGPT 可能会提示transaction_context::get_script_hash()函数可能会返回一个空向量,当用于i% key_len这样的操作时可能会导致错误。这些信息对于试图调试代码和了解潜在错误来源的人来说有一定帮助。

例③:处理移动字节码

除了总结代码语义外,我们也很好奇 ChatGPT 是否能理解不同格式的 Move 字节码。经过测试,我们发现当 Move 字节码以文本形式书写时,ChatGPT 能够理解它,然而并不能解释原始的字节码指令并提供关于其含义或行为的信息。

提问:可否解释以下字节码?
FunctionDefinition {  function: FunctionHandleIndex(1),  visibility: Private,  is_entry: false,  acquires_global_resources: [],  code: Some(CodeUnit {    locals: SignatureIndex(9), code: [Call(11), StLoc(3), ImmBorrowLoc(3), CallGeneric(0), ImmBorrowLoc(3), VecLen(11), StLoc(4), VecPack(11, 0), StLoc(1), LdU64(0), StLoc(2), CopyLoc(2), ImmBorrowLoc(0), VecLen(11), Lt, BrFalse(35), Branch(17), MutBorrowLoc(1), ImmBorrowLoc(0), CopyLoc(2), VecImmBorrow(11), ReadRef, ImmBorrowLoc(3), CopyLoc(2), CopyLoc(4), Mod, VecImmBorrow(11), ReadRef, Xor, VecPushBack(11), MoveLoc(2), LdU64(1), Add, StLoc(2), Branch(11), MoveLoc(1), Ret] }) },

ChatGPT 的回答:你提供的代码是一个用 Move 字节码编写的函数定义。该函数是由 FunctionDefinition 块定义的,它指定了该函数的Function句柄、它的可见性(在本例中是Private)、它是否是一个入口点(在本例中是false)、它所获取的全局资源(在本例中没有)以及该函数的代码。

函数的代码本身是一串字节码指令,每条指令都执行一个特定的操作。例如,Call指令调用函数,StLoc指令在局部变量中存储值,ImmBorrowLoc指令不可更改地借用局部变量,等等。

如果不了解代码的使用环境以及各种指令和值的含义,就很难对代码的功能进行详细的解释。然而,通常情况下这段代码似乎定义了一个调用其他函数、操纵局部变量并执行一些算术和逻辑运算的函数。

它还使用了向量操作,如VecLenVecPushBack,并不可更改地借用局部变量。总的来说,这段代码看起来很复杂,因此需要更多的信息来了解它的确切功能。

ChatGPT 回答的结果在某种程度上是意料之中的。

我们可以理解 ChatGPT 未能提供对代码深刻理解的情况——因为 ChatGPT 是一个语言模型,它目前还没有专业到可以理解 Move 字节码的程度。尽管如此,它仍然可为所提供的程序生成有意义的描述。


局限性

然而,需要注意的是,ChatGPT 有其局限性。它可以理解 Move 源代码的基本内容,并提供其语义的一般解释,但它无法进行详细的逻辑模拟或提供有关代码行为的可靠信息。

换句话说,ChatGPT 可以成为快速理解用 Move 编写的代码的有用工具,但不应该依赖它来完成更高级的任务或对代码行为进行详细分析。

例④:Target Branch 的代码分析失败

提问:鉴于Initialize_balance设置为 10,res.balance 的初始值设置为 10。我们怎样调用函数才能让res.q3true( 假设我们可以多次调用该函数 )
public entry fun add(account: &signer, choice: u8, number: u8) acquires Challenge {        let res = borrow_global_mut<Challenge>(signer::address_of(account));        assert!(number <= 5, 0);        if (choice == 1) {            res.balance = res.balance + number;        } else if (choice == 2) {            res.balance = res.balance * number;        } else if (choice == 3) {            res.balance = res.balance << number;        };
if (!res.q3 && res.balance < Initialize_balance) { res.q3 = true; } }

ChatGPT 的回答:要调用add函数并将res.q3设置为true,你可以在调用函数时将choice设置为3,将number设置为使res.balance左移数位后小于Initialize_balance的值。

例如,如果res.balance的初始值是 10,你可以调用函数,选择设置为3,数字设置为3,这将使res.balance左移 3 位,结果值为80。由于这个值大于Initialize_balance,而Initialize_balance被设置为10,所以add函数中的 if 条件将为假,res.q3将保持为false

然而,如果你在调用函数时将choice设置为3number设置为2res.balance将被左移 2 位,结果值为40。由于这小于Initialize_balanceadd函数中的 if 条件将为真,res.q3将被设置为true

因此,为了调用该函数并将res.q3设置为真,你可以在调用 add 函数时choice设置为3,将number设置为一个可使res.balancenumber左移后小于Initialize_balance的值。

在这种情况下,ChatGPT 未能给出正确答案,而是试图说明 40 是小于 10 的。


写在最后

这一次通过使用 ChatGPT 来解决 CTF 总体上来说是一次有价值的体验。

ChatGPT 对于用 Move 编写的代码具备理解和总结的能力,这对开发人员很有帮助。

尽管其同样具备一定的局限性,但是我们相信它仍旧可以作为一个有用的工具,以帮助 Move 语言的开发者进行相应操作。

除此之外,本文还有一个隐藏彩蛋:除了ChatGPT 提供的答案外,本文的部分是由ChatGPT 生成的文本撰写的。也就是说,如果把ChatGPT 的回答也算在内,本文的近90%属于人工智能的编辑产物。ChatGPT 虽然不是 100% 完美,但不得不说,它的确有着为人称道之处。

往期长文回顾

Web3 安全公司 CertiK 完成 20 亿美元估值 B3 轮融资,Insight Partners,Tiger,高盛,红杉参投

软银愿景基金进军 Web3 安全行业,领投 CertiK 6000 万美元新一轮投资

红杉资本布局区块链安全赛道,以近 10 亿美元估值领投 CertiK 8000 万美元 B2 轮

Tiger 布局区块链安全赛道,领投 CertiK 2400 万美元 B+ 轮

区块链安全赛道最大单笔融资,CertiK B 轮融资 3700 万美元

快到碗里来 | 微软等巨头企业领导者加入 CertiK,共筑重量级管理团队

全球邀请函 | CertiK 写给挣扎在理想和现实中的你的一封信

一键查询安全排行榜——DeFi 的安全洞察数据库

CertiK Skynet 天网扫描系统:绕道土狗,竟如此简单?

想知道项目的审计情况,看看项目的审计报告?攻略和入口在这!

【免责声明】市场有风险,投资需谨慎。本文不构成投资建议,用户应考虑本文中的任何意见、观点或结论是否符合其特定状况。据此投资,责任自负。

专栏文章
查看更多
数据请求中

推荐专栏

数据请求中

一起「遇见」未来

DOWNLOAD FORESIGHT NEWS APP

Download QR Code