提示されたPythonのコードは、base64でエンコードされた文字列をbase64でデコードし、それをzlibで解凍した結果をmarshalで読み込んでexecで実行しています。marshalで読み込んだコードはPythonのバイトコードになっているので、disで逆アセンブルします。Handcrafted pyc
195 Teams solved.
Description
Can your brain be a Python VM? (Please use Python 2.7)
Hint
None
逆アセンブルした結果は次のとおりです。>>> import dis>>> import marshal,zlib,base64>>> code = marshal.loads(zlib.decompress(base64.b64decode('eJyNVktv00AQXm/eL0igiaFA01IO4cIVCUGFBBJwqRAckLhEIQmtRfPwI0QIeio/hRO/hJ/CiStH2M/prj07diGRP43Hs9+MZ2fWMxbnP6mux+oK9xVMHPFViLdCTB0xkeKDFEFfTIU4E8KZq8dCvB4UlN3hGEsdddXU9QTLv1eFiGKGM4cKUgsFCNLFH7dFrS9poayFYmIZm1b0gyqxMOwJaU3r6xs9sW1ooakXuRv+un7Q0sIlLVzOCZq/XtsK2oTSYaZlStogXi1HV0iazoN2CV2HZeXqRQ54TlJRb7FUlKyUatISsdzo+P7UU1Gb1POdMruckepGwk9tIXQTftz2yBaT5JQovWvpSa6poJPuqgao+b9l5Aj/R+mLQIP4f6Q8Vb3g/5TB/TJxWGdZr9EQrmn99fwKtTvAZGU7wzS7GNpZpDm2JgCrr8wrmPoo54UqGampFIeS9ojXjc4E2yI06bq/4DRoUAc0nVnng4k6p7Ks0+j/S8z9V+NZ5dhmrJUM/y7JTJeRtnJ2TSYJvsFq3CQt/vnfqmQXt5KlpuRcIvDAmhnn2E0t9BJ3SvB/SfLWhuOWNiNVZ+h28g4wlwUp00w95si43rZ3r6+fUIEdgOZbQAsyFRRvBR6dla8KCzRdslar7WS+a5HFb39peIAmG7uZTHVm17Czxju4m6bayz8e7J40DzqM0jr0bmv9PmPvk6y5z57HU8wdTDHeiUJvBMAM4+0CpoAZ4BPgJeAYEAHmgAUgAHiAj4AVAGORtwd4AVgC3gEmgBBwCPgMWANOAQ8AbwBHgHuAp4D3gLuARwoGmNUizF/j4yDC5BWM1kNvvlxFA8xikRrBxHIUhutFMBlgQoshhPphGAXe/OggKqqb2cibxwuEXjUcQjccxi5eFRL1fDSbKrUhy2CMb2aLyepkegDWsBwPlrVC0/kLHmeCBQ==')))>>> dis.dis(code)
さらに、main関数をdisで逆アセンブルします。1 0 LOAD_CONST 1 (<code object main at 00000000022FA1B0, file "<string>", line 1>)3 MAKE_FUNCTION 06 STORE_NAME 0 (main)4 9 LOAD_NAME 1 (__name__)12 LOAD_CONST 2 ('__main__')15 COMPARE_OP 2 (==)18 POP_JUMP_IF_FALSE 315 21 LOAD_NAME 0 (main)24 CALL_FUNCTION 027 POP_TOP28 JUMP_FORWARD 0 (to 31)>> 31 LOAD_CONST 0 (None)34 RETURN_VALUE
逆アセンブルした結果は次のとおりです。chr関数で文字コードから文字列を生成しています。>>> dis.dis(main)
上記で、2列目の数字がバイト数です。0~725バイトまでこのような処理が続いており、そこで生成される文字列は、次のとおりとなります。1 0 LOAD_GLOBAL 0 (chr)3 LOAD_CONST 1 (108)6 CALL_FUNCTION 1 l9 LOAD_GLOBAL 0 (chr)12 LOAD_CONST 1 (108)15 CALL_FUNCTION 1 l18 LOAD_GLOBAL 0 (chr)21 LOAD_CONST 2 (97)24 CALL_FUNCTION 1 a27 LOAD_GLOBAL 0 (chr)30 LOAD_CONST 3 (67)
33 CALL_FUNCTION 1 C
(略)
Call me a Python virtual machine! I can interpret Python bytecodes!!!さらに、その先のバイトコードを見てみると、上記文字列をpassword変数に格納し、入力値と比較しています。比較した結果一致していない場合、1591バイトにジャンプしています。
入力値とpasswordが一致していた場合は、以下のコードが実行されます。文字コードから文字列を生成しています。ここで生成される文字列がフラグになります。(略)741 JUMP_ABSOLUTE 759>> 744 LOAD_GLOBAL 1 (raw_input)747 JUMP_ABSOLUTE 1480>> 750 LOAD_FAST 0 (password)753 COMPARE_OP 2 (==)756 JUMP_ABSOLUTE 767>> 759 ROT_TWO760 STORE_FAST 0 (password)763 POP_TOP764 JUMP_ABSOLUTE 744
>> 767 POP_JUMP_IF_FALSE 1591
770 LOAD_GLOBAL 0 (chr)773 LOAD_CONST 17 (99)776 CALL_FUNCTION 1 c779 LOAD_GLOBAL 0 (chr)782 LOAD_CONST 10 (116)785 CALL_FUNCTION 1 t788 LOAD_GLOBAL 0 (chr)791 LOAD_CONST 14 (105)794 CALL_FUNCTION 1 i797 LOAD_GLOBAL 0 (chr)800 LOAD_CONST 9 (104)803 CALL_FUNCTION 1 h(略)
それでは、codeを実行してパスワードを入力してみます。次のとおりフラグが表示されました。
>>> exec(code)password: Call me a Python virtual machine! I can interpret Python bytecodes!!!hitcon{Now you can compile and run Python bytecode in your brain!}
フラグは、
hitcon{Now you can compile and run Python bytecode in your brain!}