网鼎杯2022re方向的两道wp(谨以此文,纪念那个遗憾的夏天)

走马灯(bushi)

前晚,我按照惯例打开电脑准备做题,然而这一次我突发奇想,点开了Bugku比赛真题的部分。

因为这些题目并不奖励金币,所以大多数选手都不太愿意去做这些题目。

就在那个时候,我无意中点击了一个标签按钮,眼前展现出了许多比赛的题目。我心里想着:“会不会有之前那次比赛的题目呢?”从那一刻起,命运的齿轮开始转动。

我移动鼠标,点击了下方醒目的"网鼎杯",然后小心翼翼地在搜索框中敲下了"2022青龙组",宛如电脑正面临着即将宕机的危险。就在按下回车的那一刹那,过去的回忆如波涛般汹涌而至......


2022.08.26,一个令人难忘的日子。细节虽以模糊,但我依然记得那天的太阳如烈焰般张扬,食堂的饭菜简直是差强人意的香,比赛的结果充满遗憾又凄凉。

那是我第二次参与此类CTF比赛。几天前,在某个群中,我与几位师傅结成团队,抱着试一试的心态参赛。我们都明白,这次晋级的可能性微乎其微,但每个人都怀揣着对即将到来的比赛的期待。尽管现在看来略感"世界以痛吻我,我却以歌声回报",然而在那时的我,年幼而纯真,依旧满心兴致地做好准备。

然而,等到了比赛当天,现实却给我们来了一记"豪油根"。。。。。。。自以为准备充足的我们还是因为比赛经验的缺乏而手忙脚乱,比赛前一个小时我们在准备录屏工具,而在前半个小时,我们则在分配每个人负责的方向。于是,当时一脸茫然的我被要求去解决Web和RE的题目。比赛开始后,情况变得更加混乱。负责Misc方向的师傅尝试解决签到题半个小时后,在群里寻求大家的帮助。然而,我们忙于解决自己负责的题目而没有留意这位师傅的请求。于是,这位师傅不得不求助外援。

只不过,这位师傅有些大意,他错误地提交了其他队伍的 flag,结果导致我们两队都被禁赛了。。。。。。。。。。


搜索结果依然将我的思绪拉回现实。。。。。。我去,还真有啊

心中突然涌动着一股莫名的激动,对于那次禁赛的遗憾让我开始考虑是否尝试解决这两道逆向题目。答案很快就在我的心中显现。于是,我决定写下这篇文章。

网鼎杯2022青龙组re(fakeshell+handmake)wp

fakeshell

做了加壳并且修改了一些东西,需要放进010改回来

把这里的fuk改回upx,然后放kali里脱壳拿出

ida64打开

shift+f12

ctrl+x

看看伪代码

关键函数

我们先看第一个处理函数

继续跳转

这里的j___intrinsic_setjmp的作用应该是在Buf中存储跳转点信息,并将当前的栈帧信息保存到v4变量中

我们看看sub_140011230干了什么

如果value的长度不是20,跳回longjmp

由此可以判断出输入的字符串长度为20

从这可以看出,它对字符串长度判断以后,对字符串的前36个字符执行异或操作,这里使用0x66执行异或运算

循环结束后,通过 j_longjmp跳转到之前设置的跳转点,并将 20 作为跳转的返回值。

好的,我们回到main

在main中,它也使用了j___intrinsic_setjmp设置一个跳转点,并将跳转点信息存储在 stru_14001D330 中。同时,将 &v2 的地址作为参数传递给函数,用于保存栈帧信息。函数的返回值存储在 v4中。

我们看看sub_1400111E5做了什么操作

这里又做了一次+10异或80u

再看看sub_140011276

好的,这里将字符串的异或值与dword_14001D000进行比较,如果相同则return

dword_14001D000的值

看到这里思路就清晰许多

它差不多就是对传入的字符串做了长度判断,然后进行异或,加10后再进行异或,最后和内存中的十六进制值作比较

根据题意我们可以构建这样一个脚本:

dword = ['4B', '48', '79', '13', '45', '30', '5C', '49', '5A', '79', '13', '70', '6D', '78', '13', '6F', '48', '5D',
         '64', '64']
flag = ""
for i in dword:
    flag += chr(((int(i, 16) ^ 0x50) - 10) ^ 0x66)
print('flag{'+flag+'}')

flag

flag{why_m0dify_pUx_SheLL}

Handmake

压缩出来是一个没有后缀名的文件

使用vs打开

识别为go语言脚本

浅看了一眼

这个脚本一共15w行............

ctrl+f 搜索main函数在哪里(本人不是很懂go,有什么解读错误还请各位及时指出)

func main() {
    var nFAzj, CuSkl string//声明了两个字符串类型的变量 nFAzj 和 CuSkl。
    jjxXf := []byte{
        37, 73, 151, 135, 65, 58, 241, 90, 33, 86, 71, 41, 102, 241, 213, 234, 67, 144, 139, 20, 112, 150, 41, 7, 158, 251, 167, 249, 24, 129, 72, 64, 83, 142, 166, 236, 67, 18, 211, 100, 91, 38, 83, 147, 40, 78, 239, 113, 232, 83, 227, 47, 192, 227, 70, 167, 201, 249, 156, 101, 216, 159, 116, 210, 152, 234, 38, 145, 198, 58, 24, 183, 72, 143, 136, 234, 246}
    KdlaH := []byte{
        191, 140, 114, 245, 142, 55, 190, 30, 161, 18, 200, 7, 21, 59, 17, 44, 34, 181, 109, 116, 146, 145, 189, 68, 142, 113, 0, 33, 46, 184, 21, 33, 66, 99, 124, 167, 201, 88, 133, 20, 211, 67, 133, 250, 62, 28, 138, 229, 105, 102, 125, 124, 208, 180, 50, 146, 67, 39, 55, 240, 239, 203, 230, 142, 20, 90, 205, 27, 128, 136, 151, 140, 222, 92, 152, 1, 222, 138, 254, 246, 223, 224, 236, 33, 60, 170, 189, 77, 124, 72, 135, 46, 235, 17, 32, 28, 245}
    fmt.Print(MPyt9GWTRfAFNvb1(jjxXf))//调用 fmt.Print 函数打印 MPyt9GWTRfAFNvb1(jjxXf) 的返回值
    fmt.Scanf("%20s", &nFAzj)//从标准输入中读取一个字符串(最多 20 个字符),并将其存储到变量 nFAzj 中
    fmt.Print(kZ2BFvOxepd5ALDR(KdlaH))
    fmt.Scanf("%20s", &CuSkl)
    vNvUO := GwSqNHQ7dPXpIG64(nFAzj)//调用 GwSqNHQ7dPXpIG64 函数,传递 nFAzj 作为参数,并将返回值存储在变量 vNvUO 中
    YJCya := ""
    mvOxK := YI3z8ZxOKhfLmTPC(CuSkl)
    if mvOxK != nil {    //如果 mvOxK 不为 nil,调用 mvOxK 函数,并将返回值赋给变量 YJCya。
        YJCya = mvOxK()
    }

    if YJCya != "" && vNvUO != "" { 	//如果 YJCya 不为空字符串且 vNvUO 不为空字符串,使用格式化字符串打印结果,将 vNvUO 和 YJCya 的值插入到字符串中
        fmt.Printf("flag{%s%s}\n", vNvUO, YJCya)
    }
}

也就是说,flag被分成了两部分,我们需要根据题意去获取flag

但是找了半天依旧是毫无头绪

只好尝试运行这个脚本

出乎意料,居然运行成功

大概意思是

输入第一个函数,它有6个参数,第三个命名为gLIhR:
输入第二个函数,它有3个调用方,并调用名为cHZv5op8rOmlAkb6的函数: 

好好好

直接搜索gLIhR

符合题意

浅浅审计一下

func suQckJYULoX1TAp3(BSteN []byte, eQObk string, gLIhR string, TYhs2 string, yaE6g string) string {
    LhDYA := make([]byte, 20)//创建了一个长度为 20 的字节切片
    nvysM := [16]byte{
        159, 73, 217, 96, 208, 80, 245, 55, 128, 180, 57, 116, 41, 23, 75, 120}//初始化了一个长度为 16 的字节数组
    for i := 0; i < 16; i++ {
        LhDYA[i] += nvysM[i] ^ BSteN[i]//将nvysM数组中的每个元素与 BSteN 数组中对应位置的元素进行异或运算,并将结果累加到LhDYA切片中
    }

    return string(LhDYA)
}

还需注意的是,第一段还用这个函数进行加密

func GwSqNHQ7dPXpIG64(cJPTR string) string {
    YrXQd := hex.EncodeToString([]byte(cJPTR))
    return fmt.Sprintf("%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c", YrXQd[22], YrXQd[19], YrXQd[20], YrXQd[21], YrXQd[28], YrXQd[10], YrXQd[20], YrXQd[7], YrXQd[29], YrXQd[14], YrXQd[0], YrXQd[18], YrXQd[3], YrXQd[24], YrXQd[27], YrXQd[31])
}

可以构造这样一个脚本得到第一段flag(不会go,用的python)

YrXQd = bytes.hex('ZlXDJkH3OZN4Mayd'.encode())
flag = YrXQd[22] + YrXQd[19] + YrXQd[20] + YrXQd[21] + YrXQd[28] + YrXQd[10] + YrXQd[20] + YrXQd[7] + YrXQd[29] + YrXQd[14] + YrXQd[0] + YrXQd[18] + YrXQd[3] + YrXQd[24] + YrXQd[27] + YrXQd[31]

print(flag)

再找第二段

符条件的只有这个

ok,查看这个函数的内容

func cHZv5op8rOmlAkb6(HIGXt []byte, VGvny string, ZOkKV string, eU0uD string) string {
    QTk4l := make([]byte, 20)
    Ek08m := [16]byte{
        167, 238, 45, 89, 160, 95, 34, 175, 158, 169, 20, 217, 68, 137, 231, 54}
    for i := 0; i < 16; i++ {
        QTk4l[i] += Ek08m[i] ^ HIGXt[i]
    }

    return string(QTk4l)
}

func UhnCm82SDGE0zLYO() string {
    SythK := []byte{
        159, 141, 72, 106, 196, 62, 16, 205, 170, 159, 36, 232, 125, 239, 208, 3}
    var Vw2mJ, Nij87, zVclR string
    return cHZv5op8rOmlAkb6(SythK, Vw2mJ, Nij87, zVclR)
}

这下就清晰多了

构建如下脚本获取flag

YrXQd = bytes.hex('ZlXDJkH3OZN4Mayd'.encode())
flag = YrXQd[22] + YrXQd[19] + YrXQd[20] + YrXQd[21] + YrXQd[28] + YrXQd[10] + YrXQd[20] + YrXQd[7] + YrXQd[29] + YrXQd[
    14] + YrXQd[0] + YrXQd[18] + YrXQd[3] + YrXQd[24] + YrXQd[27] + YrXQd[31]

QTk4l = [0] * 16
SythK = [159, 141, 72, 106, 196, 62, 16, 205, 170, 159, 36, 232, 125, 239, 208, 3]
Ek08m = [167, 238, 45, 89, 160, 95, 34, 175, 158, 169, 20, 217, 68, 137, 231, 54]
for i in range(16):
    QTk4l[i] = chr(SythK[i] ^ Ek08m[i])

flag += ''.join(QTk4l)
print('flag{%s}' % flag)

flag

flag{3a4e76449355c4148ce3da2b46019f75}

算是总结吧

现在看来,这两题两年前的我绝对不可能做得出来,不过这何尝不算是弥补了自己的遗憾呢?

在这里,我还要特别感谢那些与我一起并肩作战的师傅们。尽管结局并不如我们所愿,但那个夏天的经历,你们同我一起书写了它的句号。我认为这件事情本身就具有特别的意义。。。。。

也祝愿各位能够越来越好,加油!!!!!!

  • 37
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值