web_assembly
WebページのURLが与えられた。
アクセスすると、「Please input your name」というプロンプトが表示され、それを閉じると続いて「Please input your password」というプロンプトが表示された。
Firefox の開発者ツールで確認すると、index.wasm
というファイルを取得していたので、これをダウンロードした。
そして、これを WABT で解析することにした。
まず、AWS で AMI「Ubuntu Server 22.04 LTS (HVM), SSD Volume Type」 (ami-0fcf52bcf5db7b003) を用いて t2.micro のEC2インスタンスを立てた。
そして、そのインスタンス上で、index.wasm
をホームディレクトリに置き、WABTの README.md
に沿って以下のコマンドを実行した。
An URL of a web page was given.
Opening the page, a prompt saying "Please input your name" appeard. Closing the prompt, another prompt saying "Please input your password" appeared.
Using the Developer Tools on Firefox, I found that a file index.wasm
is fetched, so I downloaded this file.
Then, I decided to investigate this using WABT.
I started an AWS EC2 t2.micro instance with AMI "Ubuntu Server 22.04 LTS (HVM), SSD Volume Type" (ami-0fcf52bcf5db7b003).
Then, on the instance, I put the index.wasm
to the home directory and executed these commands, based on WABT README.md
.
sudo apt-get update
sudo apt-get -y upgrade
sudo apt-get -y install gcc g++ git cmake python3
git clone --recursive https://github.com/WebAssembly/wabt
cd wabt
git submodule update --init
mkdir build
cd build
cmake ..
cmake --build .
./wasm-decompile ../../index.wasm -o ../../index.dcmp
得られた index.dcmp
から「main」を検索すると、1944行目で見つかった。
I searched for "main" from the index.dcmp
. It was found at the line 1944.
export function main(a:int, b:int):int {
var c:int = f_n();
return c;
}
ここで呼ばれている関数 f_n
の定義は、531行目からあった。
The definition of function f_n
, which is called here, started from the line 531.
function f_n()
function f_n():int {
var a:int = g_a;
var b:int = 144;
var c:int_ptr = a - b;
g_a = c;
var d:int = 0;
c[35] = d;
var e:int = 128;
var f:int = c + e;
var g:int = f;
var h:int = 65952;
f_o(g, h);
var i:int = 116;
var j:int = c + i;
var k:int = j;
var l:int = 66124;
f_o(k, l);
var m:int = 104;
var n:int = c + m;
var o:int = n;
var p:int = 65948;
f_o(o, p);
var q:int = 92;
var r:int = c + q;
var s:int = r;
var t:int = 66022;
f_o(s, t);
var u:int = 80;
var v:int = c + u;
var w:int = v;
var x:int = 65642;
f_o(w, x);
var y:int = 68;
var z:int = c + y;
var aa:int = z;
var ba:int = 65821;
f_o(aa, ba);
var ca:int = 56;
var da:int = c + ca;
var ea:int = da;
var fa:int = 65809;
f_o(ea, fa);
var ga:int = 44;
var ha:int = c + ga;
var ia:int = ha;
var ja:int = 65738;
f_o(ia, ja);
var ka:int = 32;
var la:int = c + ka;
var ma:int = la;
var na:int = 65536;
f_o(ma, na);
var oa:int = env_prompt_name();
var pa:int = 20;
var qa:int = c + pa;
var ra:int = qa;
f_o(ra, oa);
var sa:int = env_prompt_pass();
var ta:int = 8;
var ua:int = c + ta;
var va:int = ua;
f_o(va, sa);
var wa:int = 82884;
var xa:int = 66157;
var ya:int = f_p(wa, xa);
var za:int = 20;
var ab:int = c + za;
var bb:int = ab;
var cb:int = f_q(ya, bb);
var db:int = 1;
f_s(cb, db);
var eb:int = 82884;
var fb:int = 66174;
var gb:int = f_p(eb, fb);
var hb:int = 8;
var ib:int = c + hb;
var jb:int = ib;
var kb:int = f_q(gb, jb);
var lb:int = 1;
f_s(kb, lb);
var mb:int = 20;
var nb:int = c + mb;
var ob:int = nb;
var pb:int = 128;
var qb:int = c + pb;
var rb:int = qb;
var sb:int = f(ob, rb);
var tb:int = 1;
var ub:int = sb & tb;
if (eqz(ub)) goto B_b;
var vb:int = 8;
var wb:int = c + vb;
var xb:int = wb;
var yb:int = 116;
var zb:int = c + yb;
var ac:int = zb;
var bc:int = f(xb, ac);
var cc:int = 1;
var dc:int = bc & cc;
if (eqz(dc)) goto B_b;
var ec:int = 82884;
var fc:int = 66099;
var gc:int = f_p(ec, fc);
var hc:int = 1;
f_s(gc, hc);
var ic:int = 82884;
var jc:int = 104;
var kc:int = c + jc;
var lc:int = kc;
var mc:int = f_q(ic, lc);
var nc:int = 92;
var oc:int = c + nc;
var pc:int = oc;
var qc:int = f_q(mc, pc);
var rc:int = 80;
var sc:int = c + rc;
var tc:int = sc;
var uc:int = f_q(qc, tc);
var vc:int = 68;
var wc:int = c + vc;
var xc:int = wc;
var yc:int = f_q(uc, xc);
var zc:int = 56;
var ad:int = c + zc;
var bd:int = ad;
var cd:int = f_q(yc, bd);
var dd:int = 44;
var ed:int = c + dd;
var fd:int = ed;
var gd:int = f_q(cd, fd);
var hd:int = 32;
var id:int = c + hd;
var jd:int = id;
var kd:int = f_q(gd, jd);
var ld:int = 1;
f_s(kd, ld);
var md:int = 0;
c[35] = md;
var nd:int = 1;
c[1] = nd;
goto B_a;
label B_b:
var od:int = 82884;
var pd:int = 66058;
var qd:int = f_p(od, pd);
var rd:int = 1;
f_s(qd, rd);
var sd:int = 0;
c[1] = sd;
label B_a:
var td:int = 8;
var ud:int = c + td;
f_dhb(ud);
var vd:int = 20;
var wd:int = c + vd;
f_dhb(wd);
var xd:int = 32;
var yd:int = c + xd;
f_dhb(yd);
var zd:int = 44;
var ae:int = c + zd;
f_dhb(ae);
var be:int = 56;
var ce:int = c + be;
f_dhb(ce);
var de:int = 68;
var ee:int = c + de;
f_dhb(ee);
var fe:int = 80;
var ge:int = c + fe;
f_dhb(ge);
var he:int = 92;
var ie:int = c + he;
f_dhb(ie);
var je:int = 104;
var ke:int = c + je;
f_dhb(ke);
var le:int = 116;
var me:int = c + le;
f_dhb(me);
var ne:int = 128;
var oe:int = c + ne;
f_dhb(oe);
var pe:int = c[35];
var qe:int = 144;
var re:int = c + qe;
g_a = re;
return pe;
}
この関数からは、関数 env_prompt_name()
および env_prompt_pass()
が呼ばれている。
これらの関数に注目し、Google Chrome で与えられたURLを開き、開発者ツールの Sources から index.wasm
を調べると、
0x001006 に call $env.prompt_name
が、0x001020 に call $env.prompt_pass
があった。
そこで、これらの周辺の動作を調べると、0x00102c の i32.add
を実行後、スタックに値 65400 (0xff78) が積まれた。
Scope → Module → memories → $memory から Memory Inspector を開き、このアドレス 0xff78 付近を調べると、プロンプトで入力した値があり、その周辺にflagの断片っぽいデータもあった。
This function calls functions env_prompt_name()
and env_prompt_pass()
.
Highlighting these functions, I opened the given URL on Google Chrome and inspected index.wasm
on "Source" tab in the Developer Tools.
As a result, I found call $env.prompt_name
at 0x001006 and call $env.prompt_oass
at 0x001020.
I checked how it behaves around this and found that a value 65400 (0xff78) is pushed to the stack after executing i32.add
at 0x00102c.
I opened the Memory Inspector from Scope → Module → memories → $memory and inspected around this address 0x00f78. As a result, I found data I entered for the prompts and something that look like fragments of the flag.
これらの断片を組み合わせることで、flagが得られた。
I obtained the flag by assembling these fragments.
Flag{Y0u_C4n_3x3cut3_Cpp_0n_Br0us3r!}
WaniCTF 2023