# NewStarCTF-2023

大一新生第一次打 ctf,这次的新人赛里收获了挺多知识
由于本人是 Re 方向的,其他的还没怎么学,所以这里只有 Re 题的 wp 哈哈
其他题可以去看看官解或其他大佬的 wp

官解

# week1

懒得写~

# week2

懒得写~

# week3

# Reverse

#

  • 考点:花指令,rc4 加密
  • flag: flag{You!FlowerMaster!YouPassTheThirdPZGALAXYlevel!}
  • 解题思路
    丢 DIE 看看,无壳,32 位
    img.png

ida 静态分析一下,main 函数有个很明显的花指令,patch 一下,将 E8 (call)->90 (nop) 即可
img.png

然后按 C 转换为 code
img.png

按 P 创建函数,一眼 rc4
img.png

Rc4_Init 和 Rc4_Crypt 都有花指令,跟上面一样,最后直接写代码解密即可拿到 flag

#include <stdio.h>
#include <string.h>
void rc4_init(unsigned char *s, unsigned char *key, unsigned long Len)
{
    int i = 0, j = 0;
    char k[256] = {0};
    unsigned char tmp = 0;
    for (i = 0; i < 256; i++)
    {
        s[i] = i;
        k[i] = key[i % Len];
    }
    for (i = 0; i < 256; i++)
    {
        j = (j + s[i] + k[i]) % 256;
        tmp = s[i];
        s[i] = s[j];
        s[j] = tmp;
    }
}
void rc4_crypt(unsigned char *s, unsigned char *Data, unsigned long Len)
{
    int i = 0, j = 0, t = 0;
    unsigned long k = 0;
    unsigned char tmp;
    for (k = 0; k < Len; k++)
    {
        i = (i + 1) % 256;
        j = (j + s[i]) % 256;
        tmp = s[i];
        s[i] = s[j];
        s[j] = tmp;
        t = (s[i] + s[j]) % 256;
        Data[k] ^= s[t];
    }
}
unsigned char enc[] = {
        0xF4, 0x87, 0xD4, 0xFA, 0x61, 0xA6, 0x71, 0x12, 0x75, 0x09,
        0xFE, 0xD8, 0xE4, 0x38, 0x97, 0x51, 0xA8, 0xDF, 0x85, 0x65,
        0xC2, 0xB2, 0x15, 0xEF, 0x1F, 0xEC, 0x69, 0xDD, 0x6E, 0xE9,
        0xCF, 0x07, 0xAE, 0xC8, 0x17, 0xF0, 0x65, 0x72, 0xE6, 0x73,
        0xA4, 0x0C, 0x87, 0x64, 0x9E, 0x9E, 0x71, 0x8C, 0x7F, 0xD7,
        0x75, 0x84
};
int main()
{
    unsigned char s[256] = {0};
    unsigned char key[] = "WOWOWOWWOWOWOW";
    rc4_init(s, key, strlen(key));
    rc4_crypt(s, enc, strlen(enc));
    printf("%s", enc);
}

# week4

# Reverse

# easy_js

  • 考点: js 混淆
  • flag: flag{h0w_you_know_h0w_t0_S1lve_js}
  • 解题思路
    首先尝试了一下使用在线工具尝试反混淆
    得到如下结果
function _0x4a2285(_0x2b5a00) {
    var _0x37bb73 = new Array(256);
    var _0x53324d = new Array(256);
    var _0x563e78;
    var _0x1be492;
    var _0x5b4a53;
    for (_0x563e78 = 0; _0x563e78 < 256; _0x563e78++) {
        _0x37bb73[_0x563e78] = _0x563e78;
        _0x53324d[_0x563e78] = _0x2b5a00.charCodeAt(_0x563e78 % _0x2b5a00.length);
    }
    for (_0x563e78 = _0x1be492 = 0; _0x563e78 < 256; _0x563e78++) {
        _0x1be492 = (_0x1be492 + _0x37bb73[_0x563e78] + _0x53324d[_0x563e78]) % 256;
        _0x5b4a53 = _0x37bb73[_0x563e78];
        _0x37bb73[_0x563e78] = _0x37bb73[_0x1be492];
        _0x37bb73[_0x1be492] = _0x5b4a53;
    }
    return _0x37bb73;
}
function _0x569454(_0x1f637f, _0x46bf6a) {
    return String.fromCharCode(_0x1f637f.charCodeAt(0) + 13) + String.fromCharCode(_0x46bf6a.charCodeAt(0) - 1) + 'wstar' + '_' + String.fromCharCode(_0x46bf6a.charCodeAt(1) + 1) + String.fromCharCode(_0x1f637f.charCodeAt(3) + 1) + 's';
}
function _0x221c90(_0x2acf55, _0x549db3) {
    var _0x300c36 = '';
    var _0x22f2ea = new Array(256);
    _0x22f2ea = _0x4a2285(_0x2acf55);
    var _0x37dfd2;
    var _0x3c262d;
    var _0x20fab4;
    _0x37dfd2 = _0x3c262d = 0;
    for (var _0x4ff9a6 = 0; _0x4ff9a6 < _0x549db3.length; _0x4ff9a6++) {
        _0x37dfd2 = (_0x37dfd2 + 1 + 1) % 256;
        _0x3c262d = (_0x3c262d + _0x22f2ea[_0x37dfd2]) % 256;
        _0x20fab4 = _0x22f2ea[_0x37dfd2];
        _0x22f2ea[_0x37dfd2] = _0x22f2ea[_0x3c262d];
        _0x22f2ea[_0x3c262d] = _0x20fab4;
        _0x300c36 += String.fromCharCode(_0x549db3.charCodeAt(_0x4ff9a6) ^ _0x22f2ea[(_0x22f2ea[_0x37dfd2] + _0x22f2ea[_0x3c262d]) % 256] ^ 3);
    }
    return _0x300c36;
}
window._0x54cd23 = _0x53816c;
var _0x24eb58 = window._0x54cd23;
function _0x53816c(_0x3cc7e4) {
    return btoa(_0x3cc7e4) === 'Cn8RHIJEVdvlrRESjETCscwQZdlhRfsRkWoHCTa0HcfLPg==';
}
function _0x499d16() {
    alert('来试试吧');
    var _0x2fd441 = document.getElementById('username').value;
    var _0x387488 = document.getElementById('password').value;
    var _0x130920 = document.getElementById('flagtext').value;
    if (_0x2fd441 === 'admin' && _0x387488 === '123456') {
        alert('正在验证账号密码------');
        alert('账号密码正确\uFF01再接再厉');
        alert('正在验证flag------');
        var _0x271a69 = _0x221c90(_0x569454(_0x2fd441, _0x387488), _0x130920);
        _0x24eb58(_0x271a69) ? alert('flag正确\uFF01') : alert('不行不行!');
    } else
        alert('不行不行');
}

通过 0x499d16 函数可以得知账号密码分别为 admin123456 ,这个会影响到 key 的结果
后面发现他会调用 0x569454 函数,通过调试,可以知道传入的参数分别为账号和密码,然后返回 key n0wstar_3js
img.png

接着走到 0x221c90 函数里,可以看到两个参数分别为 key 和输入的 flag,那么这里应该就是加密的过程了,根据反混淆的结果来看,猜测可能是 rc4 加密 (我小白,不敢保证 hhh)
img.png

接着看到 0x53816c 函数,很容易就看出来这个就一个 check 函数
btoa 就是 base64 encode,那么 decode 就是 atob 喽
Cn8RHIJEVdvlrRESjETCscwQZdlhRfsRkWoHCTa0HcfLPg== 就是正确的 flag 经过 rc4 后转为 base64 的密文了

不会吧不会吧,不会真的有人还要去自己写代码去解密吧,直接控制台调用一下就好了呀
img.png

# week5

# Reverse

# easy_js2

  • 考点: wasm, AES 加密
  • flag: flag{aes_newstarTrealstar}
  • 解题过程

这题真的是运气好意外拿了个一血哈哈
题目告诉我们 flag 的格式是 flag{加密算法_key}
加密算法应该是很好分析的,只要专注去找 key 就完事了
启动靶机,看到是一个加解密页面,下断点调试
走了几步之后,发现居然是 wasm... (查资料 ing...)

这里尝试了很多办法,还去把他转成了 c 文件,甚至 gcc 编译成了.o 丢 ida 里分析
结果就是... 看不懂一点!不过还好,通过观察可以得到使用的是 AES 加密算法
事实上去瞅一眼 wasm 的文件就能看到很明显用到了 AES (毕竟函数名都写那了)...

在调试走到 wasm 里后,查看模块,意外的发现了 getkey 函数
然后就试图在那下断点获取 key... 结果就是不知道返回值存哪里了 qwq
img.png

然后我寻思 getkey 之后,key 应该是保存在内存里的吧,
于是在调试走完 getkey 之后,去内存检查器里翻看附近的内存
嘿你别说,还真被我翻到了,可以看到很明显的字符串拼接操作
那么最后一个就是 key 啦,想着碰碰运气,提交就过了嘿嘿
img.png

# 两个字的开放世界游戏

  • 考点: erlang
  • flag: flag{Funny_erLang_x0r__😃__}
  • 解题过程
小声哔哔

这题挺有意思哈哈,刚看到是个.beam 文件有点不知所措
然后就是漫长的查资料过程 ing...
没想到在我还在啃字节码的时候就有大佬拿了一血 qwq
后来发现就是一个小地方分析错了,痛失一血

主要是前面的分析过程时间长了点,毕竟资料真的少,官方文档也有点不太清晰
解密的话就一个异或就没了

首先感谢以下资料

前往 github 下载 erlang otp
安装,启动终端,输入 erl,进入到 EShell 中
输入 io:format("~p~n",[beam_disasm:file("genshin.beam")]). (别忘了末尾的点)
然后你会得到他的反汇编形式,此时大概逻辑已经比较清晰了,加密代码都在 transform 函数里了

{beam_file,genshin,
    [{main,1,2},{module_info,0,11},{module_info,1,13}],
    [{vsn,[294325075297162417208450880208266398775]}],
    [{version,"8.3.1"},
     {options,[]},
     {source,
         [47,109,110,116,47,100,47,67,84,70,47,20986,39064,47,50,48,50,51,45,
          56,45,100,117,105,110,101,105,115,97,105,47,103,101,110,115,104,105,
          110,46,101,114,108]}],
    [{function,main,1,2,
         [{label,1},
          {line,1},
          {func_info,{atom,genshin},{atom,main},1},
          {label,2},
          {test,is_nonempty_list,{f,3},[{x,0}]},
          {get_list,{x,0},{x,1},{x,0}},
          {test,is_nil,{f,3},[{x,0}]},
          {move,{x,1},{x,0}},
          {call_only,1,{genshin,check,1}},
          {label,3},
          {move,
              {literal,"Usage: xxxxxxxx genshin.beam <input_string>~n"},
              {x,0}},
          {line,2},
          {call_ext_only,1,{extfunc,io,format,1}}]},
     {function,check,1,5,
         [{line,3},
          {label,4},
          {func_info,{atom,genshin},{atom,check},1},
          {label,5},
          {test,is_list,{f,4},[{x,0}]},
          {allocate,1,1},
          {move,{x,0},{y,0}},
          {move,{literal,[21407,31070,46,46,46,126,110]},{x,0}},
          {line,4},
          {call_ext,1,{extfunc,io,format,1}},
          {move,{integer,1},{x,1}},
          {move,nil,{x,2}},
          {move,{y,0},{x,0}},
          {init_yregs,{list,[{y,0}]}},
          {line,5},
          {call,3,{genshin,transform,3}},
          {line,6},
          {call_ext,1,{extfunc,erlang,list_to_binary,1}},
          {test,is_eq_exact,
              {f,6},
              [{tr,{x,0},{t_bitstring,8,false}},
               {literal,
                   <<107,114,102,103,130,68,118,106,107,119,88,109,131,70,
                     114,130,122,81,111,40,107,77,76,38,52,73,72,101>>}]},
          {move,{literal,[21551,21160,65281,126,110]},{x,0}},
          {line,7},
          {call_ext_last,1,{extfunc,io,format,1},1},
          {label,6},
          {move,{literal,[20851,38381,126,110]},{x,0}},
          {line,8},
          {call_ext_last,1,{extfunc,io,format,1},1}]},
     {function,transform,3,8,
         [{line,9},
          {label,7},
          {func_info,{atom,genshin},{atom,transform},3},
          {label,8},
          {test,is_nonempty_list,{f,9},[{x,0}]},
          {get_list,{x,0},{x,3},{x,0}},
          {line,10},
          {gc_bif,'bxor',
              {f,0},
              4,
              [{x,3},{tr,{x,1},{t_integer,{1,'+inf'}}}],
              {x,3}},
          {gc_bif,'+',{f,0},4,[{tr,{x,3},{t_integer,any}},{integer,4}],{x,3}},
          {line,11},
          {gc_bif,'+',
              {f,0},
              4,
              [{tr,{x,1},{t_integer,{1,'+inf'}}},{integer,1}],
              {x,1}},
          {test_heap,2,4},
          {put_list,{x,3},{x,2},{x,2}},
          {call_only,3,{genshin,transform,3}},
          {label,9},
          {test,is_nil,{f,7},[{x,0}]},
          {move,{x,2},{x,0}},
          {line,9},
          {call_ext_only,1,{extfunc,lists,reverse,1}}]},
     {function,module_info,0,11,
         [{line,0},
          {label,10},
          {func_info,{atom,genshin},{atom,module_info},0},
          {label,11},
          {move,{atom,genshin},{x,0}},
          {call_ext_only,1,{extfunc,erlang,get_module_info,1}}]},
     {function,module_info,1,13,
         [{line,0},
          {label,12},
          {func_info,{atom,genshin},{atom,module_info},1},
          {label,13},
          {move,{x,0},{x,1}},
          {move,{atom,genshin},{x,0}},
          {call_ext_only,2,{extfunc,erlang,get_module_info,2}}]}]}

接下来就是愉快的啃字节码时间啦,当然你也可以使用 AI 帮你去分析
最后给出解密脚本

data = [107, 114, 102, 103, 130, 68, 118, 106, 107, 119, 88, 109, 131, 70,
        114, 130, 122, 81, 111, 40, 107, 77, 76, 38, 52, 73, 72, 101]
for i in range(len(data)):
    data[i] = (data[i] - 4) ^ (i + 1)
for i in data:
    print(chr(i), end="")

没错,就是这么简单,然后... 原神,启动!