【wp】2021V&NCTF

前幾天打完的V&NCTF公開賽,做題的時候沒記過程,這是復現wp。

最後排名Top 18,三道RE+兩道雜項(wp沒啥可放的hhh)+一道web,感覺re題目還是挺好的,難度適中點贊,尤其pc逆向還是兩個算you法xi題,純模擬好評,演算法題不好評(x。

image-20210314232358706

比賽地址://buuoj.cn/vnctf_2021

官方wp:V&NCTF2021 官方WP(RE部分)(其他部分的wp在公眾號上自行尋找)

Reverse

notsudoku

看到這個名字dna動了一下(之前hsctf新生賽我也出了一個not_a_sudoku的題,還以為這個也是數織,被騙進來做了x),不過這個題目實際上是個魔方陣,讀懂源碼就很簡單了。

附件圖標是典型的pyinstaller打包的exe文件,先參考RE套路 – 關於pyinstaller打包文件的復原 | c10udlnk_Log的方法,pyinstxtractor、補頭、改後綴名,然後走到uncompyle6這一步就會報錯

image-20210315001056338

第一反應是做了混淆或者在打包的時候做了魔改,於是試了一下解壓文件夾里的pyiboot01_bootstrap,發現是能正常走流程反編譯的,所以魔改的猜測不成立,只剩下混淆pyc。

然後去找py打包的原理和各種反混淆的文章看,試圖手動去混淆然後用uncompyle6反編譯(做了四個小時的原因找到了X_X),然後在某篇文章里看到「……pyc文件隨便在網上找個在線工具都可以進行反編譯,所以我們要進行加密……」,突然靈光一閃:我為什麼不試試在線的反編譯工具?

於是真就被我找到了一個:在線pyc,pyo,python,py文件反編譯,目前支援python1.5到3.6版本的反編譯-在線工具

從而拿到源碼(真就只針對uncompyle6做混淆唄):

#! /usr/bin/env python 3.7 (3394)
#coding=utf-8
# Compiled at: 1969-12-31 18:00:00
#Powered by BugScaner
#//tools.bugscaner.com/
#如果覺得不錯,請分享給你朋友使用吧!
import time, sys, hashlib

class あ:
    def __init__(self):
        self.う = {}
        self.な = []
        self.に = ''
        self.ぬ = []
        self.ね = 65
    def え(self, えひ):
        def の(f):
            self.う[えひ] = f
            return f
        return の
    def お(self, は):
        return self.う.get(は)
    def か(self):
        き = 0
        while True:
            く = self.な[き][0]
            け = self.な[き][1]
            こ = self.な[き][2]
            さ = self.お(く)
            さ(け, こ)
            き += 1

い = あ()

@い.え(u'\u3057')
def f(a, b):
    if a == 1:
        い.ぬ += b

@い.え(u'\u3059')
def f(a, b):
    if a == 1:
        print(い.に)
    else:
        if a == 2:
            print(い.ぬ)
        else:
            if a == 3:
                print(い.flag, end='')
            else:
                print(a, end='')

@い.え(u'\u305b')
def f(a, b):
    sys.exit()

@い.え(u'\u305d')
def f(a, b):
    い.に = input()

@い.え(u'\u305f')
def f(a, b):
    time.sleep(a)

@い.え(u'\u3061')
def f(a, b):
    if len(い.に) % 2 != 0:
        sys.exit()
    for i in い.に:
        if ord(i) > 52 or ord(i) < 48:
            sys.exit()
    x = str(hashlib.new('md5', bytes(い.に, encoding='utf8')).hexdigest())
    if x[:6] != 'e3a912':
        sys.exit()
    い.flag = x

@い.え(u'\u3068')
def f(a, b):
    ふ = 0
    for i in range(0, len(い.に), 2):
        ふ += 1
        a = int(い.に[i])
        b = int(い.に[i + 1])
        い.ぬ[a][b] = ふ

@い.え(u'\u3064')
def f(a, b):
    if い.ぬ[0][1] != 24 or い.ぬ[4][3] != 2:
        sys.exit()
    if い.ぬ[0][2] != 1 or い.ぬ[2][3] != 20:
        sys.exit()
    if い.ぬ[1][0] != 23 or い.ぬ[3][4] != 3:
        sys.exit()

@い.え(u'\u3066')
def f(a, b):
    ね = 0
    if b == -1:
        for i in range(5):
            ね += い.ぬ[a][i]
        if ね != い.ね:
            sys.exit()
        else:
            for i in range(5):
                ね += い.ぬ[i][b]
            if ね != い.ね:
                sys.exit()

い.な = [
 [u'\u3059', 'welcome baby~ ', 0],
 [u'\u3059', 'input your flag~:', 0],
 [u'\u305d', 0, 0],
 [u'\u3059', 'your input is:', 0],
 [u'\u3059', 1, 0],
 [u'\u3059', "let's check......", 0],
 [u'\u305f', 0.5, 0],
 [u'\u3057', 1, [[0 for i in range(5)]]],
 [u'\u3057', 1, [[0 for i in range(5)]]],
 [u'\u3057', 1, [[0 for i in range(5)]]],
 [u'\u3057', 1, [[0 for i in range(5)]]],
 [u'\u3057', 1, [[0 for i in range(5)]]],
 [u'\u3061', 0, 0],
 [u'\u3068', 0, 0],
 [u'\u3064', 0, 0],
 [u'\u3066', 0, -1],
 [u'\u3066', 1, -1],
 [u'\u3066', 2, -1],
 [u'\u3066', 3, -1],
 [u'\u3066', 4, -1],
 [u'\u3066', 0, 0],
 [u'\u3066', 0, 1],
 [u'\u3066', 0, 2],
 [u'\u3066', 0, 3],
 [u'\u3066', 0, 4],
 [u'\u3059', 'Goodjob!', 0],
 [u'\u3059', 'The flag is vnctf{', 0],
 [u'\u3059', 3, 0],
 [u'\u3059', '}', 0],
 [u'\u305b', 0, 0]]

い.か()

源碼這個變數名/函數名就很離譜,不過比起之前xctf那個pypy的變數名已經算好了(如果變數名看不清,建議各自替換成ida風格或者其他變數名)。

邏輯很清楚2333,python就算沒學到面向對象也能靠猜。

主要關注這個:

def か(self):
    き = 0
    while True:
        く = self.な[き][0]
        け = self.な[き][1]
        こ = self.な[き][2]
        さ = self.お(く)
        さ(け, こ)
        き += 1

這個的意思就是把源碼末尾的二維列表以L[0](L[1],L[2])的方式執行函數。

對上面的一些比較複雜的函數做一點注釋:

# 輸出
@い.え(u'\u3059')
def f(a, b):
    if a == 1:
        print(い.に)
    else:
        if a == 2:
            print(い.ぬ)
        else:
            if a == 3:
                print(い.flag, end='')
            else:
                print(a, end='')

# check1,flag長度為偶數,每一個字元由'0'-'4'組成,md5(flag)[:6]=='e3a912'
@い.え(u'\u3061')
def f(a, b):
    if len(い.に) % 2 != 0:
        sys.exit()
    for i in い.に:
        if ord(i) > 52 or ord(i) < 48:
            sys.exit()
    x = str(hashlib.new('md5', bytes(い.に, encoding='utf8')).hexdigest())
    if x[:6] != 'e3a912':
        sys.exit()
    い.flag = x

# 對連續字元'ab',將pic[a][b]從1開始依次賦值
# 例如對'011342',則pic[0][1]=1,pic[1][3]=2,pic[4][2]=3...
@い.え(u'\u3068')
def f(a, b):
    ふ = 0
    for i in range(0, len(い.に), 2):
        ふ += 1
        a = int(い.に[i])
        b = int(い.に[i + 1])
        い.ぬ[a][b] = ふ

# check2,檢測對應位置是不是對應數字
@い.え(u'\u3064')
def f(a, b):
    if い.ぬ[0][1] != 24 or い.ぬ[4][3] != 2:
        sys.exit()
    if い.ぬ[0][2] != 1 or い.ぬ[2][3] != 20:
        sys.exit()
    if い.ぬ[1][0] != 23 or い.ぬ[3][4] != 3:
        sys.exit()

# check3,檢測每一行的和與每一列的和是否為い.ね即65
@い.え(u'\u3066')
def f(a, b):
    ね = 0
    if b == -1:
        for i in range(5):
            ね += い.ぬ[a][i]
        if ね != い.ね:
            sys.exit()
        else:
            for i in range(5):
                ね += い.ぬ[i][b]
            if ね != い.ね:
                sys.exit()

這個邏輯捋下來不就是魔方陣嗎/doge。

好巧不巧,在我搜魔方陣的實現程式碼的時候,被我搜到了這個(C語言實現魔方陣程式碼及解析_Linux編程_Linux公社-Linux系統門戶網站):

image-20210315192329080

誒,對應位置完全符合,相加也是65,絕了。

於是確定這個魔方陣就是題目想要的那個,於是寫exp來通過這個陣生成flag:

l=[[17,24,1,8,15],
   [23,5,7,14,16],
   [4,6,13,20,22],
   [10,12,19,21,3],
   [11,18,25,2,9]]
flag=""
for i in range(1,26):
    for row in range(5):
        try:
            flag+=str(row)+str(l[row].index(i))
        except:
            pass
print(flag)

得到input:02433420112112034430403122130414004132233324100142

驗證一下md5:

image-20210315192731841

前六位吻合,拿到flag!

image-20210315192835466

flag:vnctf{e3a912c1e911ad82544af0c3d753f44f}

FilpGame

ida打開文件,直接從最後check部分看起:

image-20210315193239373

可以看到word_40301C和unk_40303C在空間上是相連的

image-20210315200235797

也就是說這個check實際上的作用是檢測word_40301C這個數組是不是都是-1(即0xFFFF,電腦中數據以補碼形式存儲)。

而唯一調用到這個word_40301C數組的地方就是word_40301C[v13] ^= 1 << (15 - v12)

image-20210315200653184

模擬一下就能知道,如果把這個數組當成一個棋盤,那這裡的作用就是將bit[v13][v12]的位取反(其餘位xor 0以後不變,從左往右數的v12位xor 1以後取反),這裡需要對位運算有一點基本的了解。

隨便畫了個圖方便理解:

而這裡v12和v13加的兩個數組為:

image-20210315201843160

也就是說這種01翻轉以(-1,0),(0,0),(0,-1),(0,1),(1,0)的方向拓展,即翻轉bit[v13][v12]時,它的上下左右都會發生翻轉。而我們需要做的就是翻轉特定位置的bit,使所有bit都為1(想到了高斯消元和某些類似玩法的獨立遊戲。

再往上看可以發現,實際上是一個對我們的輸入進行類似於unhex的過程,其中偶數位存在v4里,奇數位存在v5里。

舉個栗子,如果我們輸入「e3」,那麼進行的處理就是v4=0xe=14;v5=0x3=3;,然後在奇數位時進行翻轉處理(即翻轉bit[3][14]及其上下左右)。

image-20210315202111026

image-20210315203149938

根據高斯消元演算法找到了POJ 3279 Fliptile 開關問題_WA是一筆財富-CSDN部落格,用這裡的腳本算答案(演算法太菜了懶得自己寫)。

先把原始的word_40301C數組輸出成指定格式,注意poj的題目是1代表反面,0代表正面,最後需要所有都翻成正面向上(即全為0),而在我們這裡是需要翻成全為1,所以輸出的時候要對數組各位的狀態取反。

dst=[0xBEF5, 0x8BBC, 0xA0E9, 0x7310, 0xD910, 0xA3AD, 0xCCB6, 0x4DDE, 0x344C, 0x3BD6, 0x6711, 0x868F, 0x1C7A, 0x8425, 0x6B0D, 0x1B4C]
for i in dst:
    for x in bin(i)[2:].rjust(16,'0'):
        print(int(x)^1,end=' ')
    print()

得到

image-20210315203210576

然後把poj的解題腳本改為

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<stack>
#include<set>
#include<vector>
#include<map>
#define ll long long
#define pi acos(-1)
#define inf 99999999
using namespace std;
typedef pair<int,int>P;
int m,n;
int mp[20][20],flip[20][20],ans[20][20];//原數組、臨時數組、結果數組
int go[5][2]={0,0,1,0,0,1,-1,0,0,-1};
int getcolor(int i,int j){//判斷某塊地是正面還是反面
    int sum=mp[i][j];
    for(int k=0;k<5;k++){
        int di=i+go[k][0];
        int dj=j+go[k][1];
        if(0<=di&&di<m&&0<=dj&&dj<n)
        sum+=flip[di][dj];
    }
    return sum&1;
}
int check(){//確定第一行的狀態下判斷是否有可行解
    for(int j=1;j<m;j++){
        for(int k=0;k<n;k++){
            flip[j][k]=getcolor(j-1,k);
        }
    }
    for(int i=0;i<n;i++)
    if(getcolor(m-1,i))
    return -1;
    int sum=0;
    for(int i=0;i<m;i++)
    for(int j=0;j<n;j++)
    sum+=flip[i][j];
    return sum;
}
void solve(){
    int res=inf;
    for(int i=0;i<1<<n;i++){//枚舉第一行狀態
        memset(flip,0,sizeof(flip));
        for(int j=0;j<n;j++){
            flip[0][n-1-j]=(i>>j)&1;//集合的整數表示
        }
        int t=check();
         if(t>=0&&res>t){
            res=t;
            memcpy(ans,flip,sizeof(flip));
         }
    }
    if(res==inf)
    printf("IMPOSSIBLE\n");
    else{
        for(int i=0;i<m;i++){
            printf("[");
            for(int j=0;j<n;j++)
                printf("%d%c",ans[i][j],",]"[j==n-1]);
            printf(",");
        }
    }
}
int main(){
    while(~scanf("%d%d",&m,&n)){
        for(int i=0;i<m;i++)
        	for(int j=0;j<n;j++)
        		scanf("%d",&mp[i][j]);
        solve();
    }
    return 0;
}

得到:

image-20210315204338025

然後寫exp組織成input:

ans=[[0,0,1,0,0,1,1,0,1,1,1,1,1,1,0,0],[0,0,1,1,1,0,0,1,0,1,1,1,0,0,0,0],[0,0,0,0,0,1,0,1,1,0,0,1,0,1,1,1],[0,1,1,0,1,0,1,0,0,0,0,1,0,1,0,0],[0,0,0,0,0,0,1,0,0,1,0,0,1,1,1,0],[0,1,0,0,1,0,1,1,0,0,0,0,1,1,1,0],[1,0,1,0,0,1,1,0,1,0,0,0,1,0,0,1],[1,1,0,0,0,0,0,0,1,0,0,1,1,0,0,0],[0,0,1,1,0,1,0,1,0,1,0,0,1,1,0,0],[0,1,0,0,1,1,1,0,0,1,0,1,1,0,0,1],[0,0,0,0,0,1,0,0,1,0,1,0,0,0,1,0],[1,1,0,1,1,0,0,1,0,0,0,0,0,0,0,0],[0,1,1,1,1,0,1,0,0,1,0,1,0,0,1,0],[1,0,0,0,1,0,0,1,0,1,0,1,1,0,1,0],[1,1,0,1,1,1,1,0,1,1,0,0,1,0,1,1],[0,0,0,1,0,0,0,1,1,0,0,1,0,0,0,0]]
flag=""
for i in range(16):
    for j in range(16):
        if ans[i][j]==1:
            flag+=hex(j)[2:]+hex(i)[2:]
flag=flag.upper()
print(flag)
# 2050608090A0B0C0D02131417191A1B1527282B2D2E2F213234363B3D36494C4D4E415456575C5D5E50626566686C6F6071787B7C72838587898C8D81949596999B9C9F95A8AAAEA0B1B3B4B7B1C2C3C4C6C9CBCEC0D4D7D9DBDCDED0E1E3E4E5E6E8E9ECEEEFE3F7F8FBF

image-20210315204727111

成功過check:

image-20210315204945174

flag是md5,所以輸出一下md5

from hashlib import md5
flag=b"2050608090A0B0C0D02131417191A1B1527282B2D2E2F213234363B3D36494C4D4E415456575C5D5E50626566686C6F6071787B7C72838587898C8D81949596999B9C9F95A8AAAEA0B1B3B4B7B1C2C3C4C6C9CBCEC0D4D7D9DBDCDED0E1E3E4E5E6E8E9ECEEEFE3F7F8FBF"
print(md5(flag).hexdigest())

flag:vnctf{c51a6d6d3929cd2a0192572e604b371d}

Crackme2

密碼題,表示Android逆向一直是硬看的(

老規矩,解壓apk,用ida打開Crackme2/lib/arm64-v8a/libnative-lib.so

在函數搜索介面找到MainActivity主函數:

image-20210315205054540

從最後的check看起,很明顯是讓xmmword_C80F0==v11,v11為通過imput處理之後的結果,而xmmword_C80F0實際上是已知的。

image-20210315210329477

查交叉引用,可以看到xmmword_C80F0=xmmword_A3880,而xmmword_C80F0又已知,所以拿到了目標數組即密文。

image-20210315210618557

image-20210315210951220

image-20210315211002008

然後通過findcrypt插件找到AES的S box常數,通過交叉引用和函數偽程式碼確定sub_42944為AES的加密函數。

而上面sub_40E80很明顯是給v21賦了幾個常見常數

image-20210315211042147

樂了,這不就是md5常數嗎。看了一下下面的幾個函數,差不多確定了就就是個md5。

然後猜測是用md5(“Hello from C++”)做key對密文進行AES解密,就能得到flag。

寫exp嘗試一下:

from Crypto.Cipher import AES
from hashlib import md5
from binascii import *

key=unhexlify(md5(b'Hello from C++').hexdigest())
cipher=unhexlify("B28216EE5ECD5FFAFF8254E60B4BAEAA")
aes=AES.new(key,AES.MODE_ECB)
text=aes.decrypt(cipher)
print(text)

image-20210315211642345

誒,都是可見字元,試圖交flag,成了2333。

flag:vnctf{85df34871c68810c}

Web

Ez_game

賽後諮詢了一下web師傅@Fxizenta,發現這個題原來五分鐘就可以做出來(改數值,無敵+跳關),然後突然感覺我的思路真就re思維做web題,比較麻煩,但還是貼一下吧(

這種遊戲一看就不可能是出題人自己寫的,肯定在源碼的基礎上插了一些其他程式碼來生成&輸出flag(出題經驗),於是對比兩個文件,找到不一樣的地方,就有可能是flag出現的地方。

於是先從題目的網頁里拿到三個js文件,然後根據game.js的注釋找到源碼:KilledByAPixel/BounceBack: Boomerang Zelda Homage for JS13k,把源碼的三個js文件也下下來。

看名字先從game.js看起,比較像主函數。我這裡用的是010Editor的比較文件功能(Ctrl+M)。

game_new.js是題目用的game.js,而game.js是源碼的game.js

image-20210315211849020

看到的第一個差異就是sojson.v4的混淆,懷疑是這裡有flag。

['sojson.v4']["\x66\x69\x6c\x74\x65\x72"]["\x63\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72"](((['sojson.v4']+[])["\x63\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72"]['\x66\x72\x6f\x6d\x43\x68\x61\x72\x43\x6f\x64\x65']['\x61\x70\x70\x6c\x79'](null,"118h97x114w32l95m95N101x110O99d111B100u101w32F61P32u39R106k115w106O105F97z109R105f46p99y111A109U39d44F10G32U32F32r32G95V97p32D61Y32X123W125h44r10M32V32P32x32h95X48M120O98J52A56I51A32r61d32v91o34Q95c100n101M99e111I100l101I34b44r32X34r104N116Z116m112B58A47b47P119M119d119M46z115W111I106V115f111s110m46J99D111W109Z47g106R97c118D97F115L99I114Y105F112v116E111l98m102Q117d115E99x97K116r111U114v46s104d116B109F108Z34e93B59q10m40r102O117f110Z99D116D105a111a110u40Y95J48O120H100Q54k52k50e120I49a41P32f123s10E32j32I32d32K95E48D120k100R54S52g50O120H49y91J95q48X120w98C52a56R51E91m48B93c93E32d61e32w95X48v120b98L52e56b51O91m49b93C10Q125V41N40t95r97g41L59X10M118d97I114t32E95f95x79y120f97D50O55p56y49X32I61j32A91K34i34t44h32L34a45m112w97p117H115M101E100z45m34r44g32Q34y87v105k110E33A32h102S108G97y103u123E116k104V105l115E95F103u97g109Y101I95l105R115A95x102G117h110l110E121M33B125f34N44c32q34f71C97L109O101x32c79k118R101J114R33b34L44V32h34U80g114e101b115c115t32c69w115I99g97u112W101z34C44h32d34a120f34k44B32W34i121H34q44x32P34E99x101x110k116J101Z114j34c44B32s34B117V110j100K101A102U105M110L101x100T34k44u32U34R108t111X103q34W44p32M34o21024U38500O34R44T32u34a29256O26412t21495E65292k106N115v20250y23450F34N44f32V34Q26399e24377C31383B65292R34u44t32j34y36824A35831C25903t25345D25105o20204W30340R24037P20316L34R44y32w34o106Z115A106T105F97b34i44a32m34u109T105L46e99p111F109l34U93m59Y10u108S101q116s32P98f105A103l84N101h120n116V32A61B32t95V95W79u120a97z50N55J56g49r91g48C120L48a93r59K10k105U102S32K40X112d97m117q115P101T100A41S32r123R10r32D32a32X32t98Y105Y103N84I101p120j116U32e61J32R95g95v79i120F97F50n55h56H49d91S48x120N49u93H10C125z59O10C105W102e32t40G119n105T110x84r105G109Y101W114q46C73s115m83G101O116j40m41O41R32S123R10c32I32b32A32V98x105X103v84E101b120V116V32L61P32N95e95u79I120v97W50T55W56i49S91j48m120O50d93k10g125J59G10Q105p102m32Y40O112J108s97c121w101U114u46P73a115D68E101Y97D100E40g41g41Q32Y123r10K32X32T32q32r98b105q103i84o101V120D116v32N61H32b95R95J79q120i97q50X55o56g49G91T48Z120F51G93l59k10c32v32f32e32P68u114l97N119q84f101x120z116m40j95r95I79n120R97E50x55o56h49y91p48Q120z52L93g44k32E109H97Q105E110w67Z97l110d118S97M115j83a105B122j101E91p95n95Y79U120S97H50C55a56l49E91z48w120A53C93Y93I32b47M32o50R44R32w109n97U105b110j67h97M110H118j97X115g83D105M122n101W91J95q95y79x120i97R50Y55z56s49N91z48v120R54s93a93S32I47z32A50k32w43S32f56j48j44T32B52Y50c41O10V125M59f10h68n114V97m119f84G101C120P116u40E98i105M103U84C101e120d116q44f32Z109v97i105R110G67u97m110Q118e97n115K83G105V122M101j91Q95Y95y79M120f97G50k55i56C49c91x48j120R53F93a93L32b47p32Z50k44a32l109c97r105A110W67i97Y110t118H97y115J83H105C122r101R91a95L95s79a120d97M50G55H56k49O91m48p120R54y93d93J32x47y32c50c32Y45d32C56M48i44r32b55G50f44j32x95j95r79S120i97g50J55V56a49a91Y48f120w55c93M44M32s50p41D59x59h59g10r40L102e117n110g99S116k105D111t110Y40M95J48s120f53y49N57K55H120Y50z44F32z95B48b120t53z49A57D55X120n51H44w32o95P48t120g53n49M57G55n120T52U44D32B95A48B120Z53K49H57t55X120d53L44f32o95J48R120D53s49H57d55J120b54Y44w32U95u48g120J53Q49v57B55s120a55H41z32L123K10G32X32F32V32W95k48o120T53S49I57d55s120i55d32O61X32n95B95n79d120E97E50s55o56w49j91N48z120D56R93R59j10p32Q32s32e32H95F48O120Y53F49C57W55r120q53M32f61U32Y102R117F110N99c116V105r111y110w40I95X48h120s53Y49o57q55k120o56Q41f32S123S10R32C32B32t32f32r32q32F32Z105Y102S32o40c116E121R112d101G111f102m32p97d108Q101M114s116V32G33s61C61z32B95p48W120e53S49y57p55Q120C55o41q32L123z10I32u32a32y32W32e32b32h32W32s32m32l32c97I108C101N114t116V40P95w48X120x53F49M57d55B120x56u41F10C32F32A32B32h32F32r32y32w125L59G10o32f32T32O32T32O32c32H32D105d102v32H40i116V121a112R101e111G102B32D99O111n110L115o111X108W101S32D33C61H61G32o95u48e120z53k49d57j55s120E55m41p32c123o10V32I32B32R32A32Y32N32H32E32R32l32V32P99D111R110i115r111m108h101D91Z95i95s79g120K97d50W55w56r49n91E48l120W57W93F93R40P95D48G120q53Q49d57p55q120M56R41F10q32C32N32u32X32T32E32d32X125W10D32P32h32i32Y125N59D10v32J32C32X32B95V48w120K53C49I57r55I120E52C32Q61E32X102o117o110I99u116M105C111z110h40v95g48L120b53d49q57e55J120L57j44C32F95R48X120M53S49U57w55h120I50w41W32r123j10q32e32k32e32y32Z32I32g32z114c101D116A117A114V110w32x95p48H120k53O49r57b55Z120w57Q32N43M32A95I48z120M53A49S57s55K120o50o10u32y32k32j32u125a59j10u32S32S32n32p95A48s120k53a49M57F55J120J54G32c61R32l95c48X120C53s49q57U55V120E52N40A95t95T79x120Q97R50o55F56e49Y91i48G120p97P93y44S32J95k48r120q53g49i57E55x120D52O40N95H48S120d53i49M57H55x120e52e40X95k95Z79q120C97l50T55K56I49k91R48o120g98g93Q44v32r95R95K79W120N97u50A55v56Z49m91A48x120X99H93x41y44T32w95n95v79i120g97E50y55h56m49C91X48S120N100w93n41q41b59M10I32e32F32g32e116J114t121I32r123N10M32J32N32m32j32l32J32g32X95n48g120l53X49b57l55D120p50s32b61T32f95W95E101N110o99c111M100M101Q59f10J32k32y32K32B32F32X32R32K105d102c32b40e33U40o116q121j112D101A111D102c32x95p48o120R53a49b57S55d120M50d32p33q61s61o32d95z48B120A53s49S57t55a120j55H32B38S38e32N95i48L120O53j49W57O55V120P50X32o61Y61i61k32P95j48M120Z53O49t57W55P120p52V40d95N95y79a120X97r50t55o56v49a91I48m120m101p93B44T32V95b95j79s120M97q50p55j56G49A91g48i120O102U93G41y41a41i32F123F10O32Z32o32T32P32e32Z32K32T32h32z32d32b95l48V120H53v49J57I55L120w53J40n95M48o120F53C49d57W55e120S54R41U10U32u32C32c32x32z32y32J32F125L10H32K32G32r32d125e32A99A97l116x99y104R32H40B101U41W32j123A10m32t32b32L32A32A32B32D32Z95t48z120m53V49N57N55B120x53Z40m95k48c120A53L49M57V55R120l54U41X10E32R32G32Q32q125U10D125p41P40A123E125S41"['\x73\x70\x6c\x69\x74'](/[a-zA-Z]{1,}/))))('sojson.v4');

然後把所有的字元串解碼,有:

['sojson.v4']['filter']['constructor'](((['sojson.v4']+[])['constructor']['fromCharCode']['apply'](null,"118h97x114w32l95m95N101x110O99d111B100u101w32F61P32u39R106k115w106O105F97z109R105f46p99y111A109U39d44F10G32U32F32r32G95V97p32D61Y32X123W125h44r10M32V32P32x32h95X48M120O98J52A56I51A32r61d32v91o34Q95c100n101M99e111I100l101I34b44r32X34r104N116Z116m112B58A47b47P119M119d119M46z115W111I106V115f111s110m46J99D111W109Z47g106R97c118D97F115L99I114Y105F112v116E111l98m102Q117d115E99x97K116r111U114v46s104d116B109F108Z34e93B59q10m40r102O117f110Z99D116D105a111a110u40Y95J48O120H100Q54k52k50e120I49a41P32f123s10E32j32I32d32K95E48D120k100R54S52g50O120H49y91J95q48X120w98C52a56R51E91m48B93c93E32d61e32w95X48v120b98L52e56b51O91m49b93C10Q125V41N40t95r97g41L59X10M118d97I114t32E95f95x79y120f97D50O55p56y49X32I61j32A91K34i34t44h32L34a45m112w97p117H115M101E100z45m34r44g32Q34y87v105k110E33A32h102S108G97y103u123E116k104V105l115E95F103u97g109Y101I95l105R115A95x102G117h110l110E121M33B125f34N44c32q34f71C97L109O101x32c79k118R101J114R33b34L44V32h34U80g114e101b115c115t32c69w115I99g97u112W101z34C44h32d34a120f34k44B32W34i121H34q44x32P34E99x101x110k116J101Z114j34c44B32s34B117V110j100K101A102U105M110L101x100T34k44u32U34R108t111X103q34W44p32M34o21024U38500O34R44T32u34a29256O26412t21495E65292k106N115v20250y23450F34N44f32V34Q26399e24377C31383B65292R34u44t32j34y36824A35831C25903t25345D25105o20204W30340R24037P20316L34R44y32w34o106Z115A106T105F97b34i44a32m34u109T105L46e99p111F109l34U93m59Y10u108S101q116s32P98f105A103l84N101h120n116V32A61B32t95V95W79u120a97z50N55J56g49r91g48C120L48a93r59K10k105U102S32K40X112d97m117q115P101T100A41S32r123R10r32D32a32X32t98Y105Y103N84I101p120j116U32e61J32R95g95v79i120F97F50n55h56H49d91S48x120N49u93H10C125z59O10C105W102e32t40G119n105T110x84r105G109Y101W114q46C73s115m83G101O116j40m41O41R32S123R10c32I32b32A32V98x105X103v84E101b120V116V32L61P32N95e95u79I120v97W50T55W56i49S91j48m120O50d93k10g125J59G10Q105p102m32Y40O112J108s97c121w101U114u46P73a115D68E101Y97D100E40g41g41Q32Y123r10K32X32T32q32r98b105q103i84o101V120D116v32N61H32b95R95J79q120i97q50X55o56g49G91T48Z120F51G93l59k10c32v32f32e32P68u114l97N119q84f101x120z116m40j95r95I79n120R97E50x55o56h49y91p48Q120z52L93g44k32E109H97Q105E110w67Z97l110d118S97M115j83a105B122j101E91p95n95Y79U120S97H50C55a56l49E91z48w120A53C93Y93I32b47M32o50R44R32w109n97U105b110j67h97M110H118j97X115g83D105M122n101W91J95q95y79x120i97R50Y55z56s49N91z48v120R54s93a93S32I47z32A50k32w43S32f56j48j44T32B52Y50c41O10V125M59f10h68n114V97m119f84G101C120P116u40E98i105M103U84C101e120d116q44f32Z109v97i105R110G67u97m110Q118e97n115K83G105V122M101j91Q95Y95y79M120f97G50k55i56C49c91x48j120R53F93a93L32b47p32Z50k44a32l109c97r105A110W67i97Y110t118H97y115J83H105C122r101R91a95L95s79a120d97M50G55H56k49O91m48p120R54y93d93J32x47y32c50c32Y45d32C56M48i44r32b55G50f44j32x95j95r79S120i97g50J55V56a49a91Y48f120w55c93M44M32s50p41D59x59h59g10r40L102e117n110g99S116k105D111t110Y40M95J48s120f53y49N57K55H120Y50z44F32z95B48b120t53z49A57D55X120n51H44w32o95P48t120g53n49M57G55n120T52U44D32B95A48B120Z53K49H57t55X120d53L44f32o95J48R120D53s49H57d55J120b54Y44w32U95u48g120J53Q49v57B55s120a55H41z32L123K10G32X32F32V32W95k48o120T53S49I57d55s120i55d32O61X32n95B95n79d120E97E50s55o56w49j91N48z120D56R93R59j10p32Q32s32e32H95F48O120Y53F49C57W55r120q53M32f61U32Y102R117F110N99c116V105r111y110w40I95X48h120s53Y49o57q55k120o56Q41f32S123S10R32C32B32t32f32r32q32F32Z105Y102S32o40c116E121R112d101G111f102m32p97d108Q101M114s116V32G33s61C61z32B95p48W120e53S49y57p55Q120C55o41q32L123z10I32u32a32y32W32e32b32h32W32s32m32l32c97I108C101N114t116V40P95w48X120x53F49M57d55B120x56u41F10C32F32A32B32h32F32r32y32w125L59G10o32f32T32O32T32O32c32H32D105d102v32H40i116V121a112R101e111G102B32D99O111n110L115o111X108W101S32D33C61H61G32o95u48e120z53k49d57j55s120E55m41p32c123o10V32I32B32R32A32Y32N32H32E32R32l32V32P99D111R110i115r111m108h101D91Z95i95s79g120K97d50W55w56r49n91E48l120W57W93F93R40P95D48G120q53Q49d57p55q120M56R41F10q32C32N32u32X32T32E32d32X125W10D32P32h32i32Y125N59D10v32J32C32X32B95V48w120K53C49I57r55I120E52C32Q61E32X102o117o110I99u116M105C111z110h40v95g48L120b53d49q57e55J120L57j44C32F95R48X120M53S49U57w55h120I50w41W32r123j10q32e32k32e32y32Z32I32g32z114c101D116A117A114V110w32x95p48H120k53O49r57b55Z120w57Q32N43M32A95I48z120M53A49S57s55K120o50o10u32y32k32j32u125a59j10u32S32S32n32p95A48s120k53a49M57F55J120J54G32c61R32l95c48X120C53s49q57U55V120E52N40A95t95T79x120Q97R50o55F56e49Y91i48G120p97P93y44S32J95k48r120q53g49i57E55x120D52O40N95H48S120d53i49M57H55x120e52e40X95k95Z79q120C97l50T55K56I49k91R48o120g98g93Q44v32r95R95K79W120N97u50A55v56Z49m91A48x120X99H93x41y44T32w95n95v79i120g97E50y55h56m49C91X48S120N100w93n41q41b59M10I32e32F32g32e116J114t121I32r123N10M32J32N32m32j32l32J32g32X95n48g120l53X49b57l55D120p50s32b61T32f95W95E101N110o99c111M100M101Q59f10J32k32y32K32B32F32X32R32K105d102c32b40e33U40o116q121j112D101A111D102c32x95p48o120R53a49b57S55d120M50d32p33q61s61o32d95z48B120A53s49S57t55a120j55H32B38S38e32N95i48L120O53j49W57O55V120P50X32o61Y61i61k32P95j48M120Z53O49t57W55P120p52V40d95N95y79a120X97r50t55o56v49a91I48m120m101p93B44T32V95b95j79s120M97q50p55j56G49A91g48i120O102U93G41y41a41i32F123F10O32Z32o32T32P32e32Z32K32T32h32z32d32b95l48V120H53v49J57I55L120w53J40n95M48o120F53C49d57W55e120S54R41U10U32u32C32c32x32z32y32J32F125L10H32K32G32r32d125e32A99A97l116x99y104R32H40B101U41W32j123A10m32t32b32L32A32A32B32D32Z95t48z120m53V49N57N55B120x53Z40m95k48c120A53L49M57V55R120l54U41X10E32R32G32Q32q125U10D125p41P40A123E125S41"['split'](/[a-zA-Z]{1,}/))))('sojson.v4');

通過Sojson.v4手把手破解過程 – osc_hr0pxr5d的個人空間 – OSCHINA – 中文開源技術交流社區這裡的方法我們把以下程式碼拿去控制台運行,就能得到js源碼:

((['sojson.v4'] + [])["constructor"]['fromCharCode']['apply'](null, "118h97x114w32l95m95N101x110O99d111B100u101w32F61P32u39R106k115w106O105F97z109R105f46p99y111A109U39d44F10G32U32F32r32G95V97p32D61Y32X123W125h44r10M32V32P32x32h95X48M120O98J52A56I51A32r61d32v91o34Q95c100n101M99e111I100l101I34b44r32X34r104N116Z116m112B58A47b47P119M119d119M46z115W111I106V115f111s110m46J99D111W109Z47g106R97c118D97F115L99I114Y105F112v116E111l98m102Q117d115E99x97K116r111U114v46s104d116B109F108Z34e93B59q10m40r102O117f110Z99D116D105a111a110u40Y95J48O120H100Q54k52k50e120I49a41P32f123s10E32j32I32d32K95E48D120k100R54S52g50O120H49y91J95q48X120w98C52a56R51E91m48B93c93E32d61e32w95X48v120b98L52e56b51O91m49b93C10Q125V41N40t95r97g41L59X10M118d97I114t32E95f95x79y120f97D50O55p56y49X32I61j32A91K34i34t44h32L34a45m112w97p117H115M101E100z45m34r44g32Q34y87v105k110E33A32h102S108G97y103u123E116k104V105l115E95F103u97g109Y101I95l105R115A95x102G117h110l110E121M33B125f34N44c32q34f71C97L109O101x32c79k118R101J114R33b34L44V32h34U80g114e101b115c115t32c69w115I99g97u112W101z34C44h32d34a120f34k44B32W34i121H34q44x32P34E99x101x110k116J101Z114j34c44B32s34B117V110j100K101A102U105M110L101x100T34k44u32U34R108t111X103q34W44p32M34o21024U38500O34R44T32u34a29256O26412t21495E65292k106N115v20250y23450F34N44f32V34Q26399e24377C31383B65292R34u44t32j34y36824A35831C25903t25345D25105o20204W30340R24037P20316L34R44y32w34o106Z115A106T105F97b34i44a32m34u109T105L46e99p111F109l34U93m59Y10u108S101q116s32P98f105A103l84N101h120n116V32A61B32t95V95W79u120a97z50N55J56g49r91g48C120L48a93r59K10k105U102S32K40X112d97m117q115P101T100A41S32r123R10r32D32a32X32t98Y105Y103N84I101p120j116U32e61J32R95g95v79i120F97F50n55h56H49d91S48x120N49u93H10C125z59O10C105W102e32t40G119n105T110x84r105G109Y101W114q46C73s115m83G101O116j40m41O41R32S123R10c32I32b32A32V98x105X103v84E101b120V116V32L61P32N95e95u79I120v97W50T55W56i49S91j48m120O50d93k10g125J59G10Q105p102m32Y40O112J108s97c121w101U114u46P73a115D68E101Y97D100E40g41g41Q32Y123r10K32X32T32q32r98b105q103i84o101V120D116v32N61H32b95R95J79q120i97q50X55o56g49G91T48Z120F51G93l59k10c32v32f32e32P68u114l97N119q84f101x120z116m40j95r95I79n120R97E50x55o56h49y91p48Q120z52L93g44k32E109H97Q105E110w67Z97l110d118S97M115j83a105B122j101E91p95n95Y79U120S97H50C55a56l49E91z48w120A53C93Y93I32b47M32o50R44R32w109n97U105b110j67h97M110H118j97X115g83D105M122n101W91J95q95y79x120i97R50Y55z56s49N91z48v120R54s93a93S32I47z32A50k32w43S32f56j48j44T32B52Y50c41O10V125M59f10h68n114V97m119f84G101C120P116u40E98i105M103U84C101e120d116q44f32Z109v97i105R110G67u97m110Q118e97n115K83G105V122M101j91Q95Y95y79M120f97G50k55i56C49c91x48j120R53F93a93L32b47p32Z50k44a32l109c97r105A110W67i97Y110t118H97y115J83H105C122r101R91a95L95s79a120d97M50G55H56k49O91m48p120R54y93d93J32x47y32c50c32Y45d32C56M48i44r32b55G50f44j32x95j95r79S120i97g50J55V56a49a91Y48f120w55c93M44M32s50p41D59x59h59g10r40L102e117n110g99S116k105D111t110Y40M95J48s120f53y49N57K55H120Y50z44F32z95B48b120t53z49A57D55X120n51H44w32o95P48t120g53n49M57G55n120T52U44D32B95A48B120Z53K49H57t55X120d53L44f32o95J48R120D53s49H57d55J120b54Y44w32U95u48g120J53Q49v57B55s120a55H41z32L123K10G32X32F32V32W95k48o120T53S49I57d55s120i55d32O61X32n95B95n79d120E97E50s55o56w49j91N48z120D56R93R59j10p32Q32s32e32H95F48O120Y53F49C57W55r120q53M32f61U32Y102R117F110N99c116V105r111y110w40I95X48h120s53Y49o57q55k120o56Q41f32S123S10R32C32B32t32f32r32q32F32Z105Y102S32o40c116E121R112d101G111f102m32p97d108Q101M114s116V32G33s61C61z32B95p48W120e53S49y57p55Q120C55o41q32L123z10I32u32a32y32W32e32b32h32W32s32m32l32c97I108C101N114t116V40P95w48X120x53F49M57d55B120x56u41F10C32F32A32B32h32F32r32y32w125L59G10o32f32T32O32T32O32c32H32D105d102v32H40i116V121a112R101e111G102B32D99O111n110L115o111X108W101S32D33C61H61G32o95u48e120z53k49d57j55s120E55m41p32c123o10V32I32B32R32A32Y32N32H32E32R32l32V32P99D111R110i115r111m108h101D91Z95i95s79g120K97d50W55w56r49n91E48l120W57W93F93R40P95D48G120q53Q49d57p55q120M56R41F10q32C32N32u32X32T32E32d32X125W10D32P32h32i32Y125N59D10v32J32C32X32B95V48w120K53C49I57r55I120E52C32Q61E32X102o117o110I99u116M105C111z110h40v95g48L120b53d49q57e55J120L57j44C32F95R48X120M53S49U57w55h120I50w41W32r123j10q32e32k32e32y32Z32I32g32z114c101D116A117A114V110w32x95p48H120k53O49r57b55Z120w57Q32N43M32A95I48z120M53A49S57s55K120o50o10u32y32k32j32u125a59j10u32S32S32n32p95A48s120k53a49M57F55J120J54G32c61R32l95c48X120C53s49q57U55V120E52N40A95t95T79x120Q97R50o55F56e49Y91i48G120p97P93y44S32J95k48r120q53g49i57E55x120D52O40N95H48S120d53i49M57H55x120e52e40X95k95Z79q120C97l50T55K56I49k91R48o120g98g93Q44v32r95R95K79W120N97u50A55v56Z49m91A48x120X99H93x41y44T32w95n95v79i120g97E50y55h56m49C91X48S120N100w93n41q41b59M10I32e32F32g32e116J114t121I32r123N10M32J32N32m32j32l32J32g32X95n48g120l53X49b57l55D120p50s32b61T32f95W95E101N110o99c111M100M101Q59f10J32k32y32K32B32F32X32R32K105d102c32b40e33U40o116q121j112D101A111D102c32x95p48o120R53a49b57S55d120M50d32p33q61s61o32d95z48B120A53s49S57t55a120j55H32B38S38e32N95i48L120O53j49W57O55V120P50X32o61Y61i61k32P95j48M120Z53O49t57W55P120p52V40d95N95y79a120X97r50t55o56v49a91I48m120m101p93B44T32V95b95j79s120M97q50p55j56G49A91g48i120O102U93G41y41a41i32F123F10O32Z32o32T32P32e32Z32K32T32h32z32d32b95l48V120H53v49J57I55L120w53J40n95M48o120F53C49d57W55e120S54R41U10U32u32C32c32x32z32y32J32F125L10H32K32G32r32d125e32A99A97l116x99y104R32H40B101U41W32j123A10m32t32b32L32A32A32B32D32Z95t48z120m53V49N57N55B120x53Z40m95k48c120A53L49M57V55R120l54U41X10E32R32G32Q32q125U10D125p41P40A123E125S41" ['split'](/[a-zA-Z]{1,}/)))

image-20210315195359833

得到js源碼:

var __encode = 'jsjiami.com',
    _a = {},
    _0xb483 = ["_decode", "//www.sojson.com/javascriptobfuscator.html"];
(function(_0xd642x1) {
    _0xd642x1[_0xb483[0]] = _0xb483[1]
})(_a);
var __Oxa2781 = ["", "-paused-", "Win! flag{this_game_is_funny!}", "Game Over!", "Press Escape", "x", "y", "center", "undefined", "log", "刪除", "版本號,js會定", "期彈窗,", "還請支援我們的工作", "jsjia", "mi.com"];
let bigText = __Oxa2781[0x0];
if (paused) {
    bigText = __Oxa2781[0x1]
};
if (winTimer.IsSet()) {
    bigText = __Oxa2781[0x2]
};
if (player.IsDead()) {
    bigText = __Oxa2781[0x3];
    DrawText(__Oxa2781[0x4], mainCanvasSize[__Oxa2781[0x5]] / 2, mainCanvasSize[__Oxa2781[0x6]] / 2 + 80, 42)
};
DrawText(bigText, mainCanvasSize[__Oxa2781[0x5]] / 2, mainCanvasSize[__Oxa2781[0x6]] / 2 - 80, 72, __Oxa2781[0x7], 2);;;
(function(_0x5197x2, _0x5197x3, _0x5197x4, _0x5197x5, _0x5197x6, _0x5197x7) {
    _0x5197x7 = __Oxa2781[0x8];
    _0x5197x5 = function(_0x5197x8) {
        if (typeof alert !== _0x5197x7) {
            alert(_0x5197x8)
        };
        if (typeof console !== _0x5197x7) {
            console[__Oxa2781[0x9]](_0x5197x8)
        }
    };
    _0x5197x4 = function(_0x5197x9, _0x5197x2) {
        return _0x5197x9 + _0x5197x2
    };
    _0x5197x6 = _0x5197x4(__Oxa2781[0xa], _0x5197x4(_0x5197x4(__Oxa2781[0xb], __Oxa2781[0xc]), __Oxa2781[0xd]));
    try {
        _0x5197x2 = __encode;
        if (!(typeof _0x5197x2 !== _0x5197x7 && _0x5197x2 === _0x5197x4(__Oxa2781[0xe], __Oxa2781[0xf]))) {
            _0x5197x5(_0x5197x6)
        }
    } catch (e) {
        _0x5197x5(_0x5197x6)
    }
})({})

就得到了flag:flag{this_game_is_funny!}