# m0leCon CTF 2020 Teaser - play-me-piano >###### tags: `wasm` >[name=whysw@PLUS] ## Attachments - problem - [index.html](https://gist.github.com/YangSeungWon/3de1311c1e03195577f4f52bae76dd02/index.html) - [chall.js](https://gist.github.com/YangSeungWon/3de1311c1e03195577f4f52bae76dd02/chall.js) - [chall.wasm](https://gist.github.com/YangSeungWon/3de1311c1e03195577f4f52bae76dd02/chall.wasm) - writeup - [chall.c](https://gist.github.com/YangSeungWon/3de1311c1e03195577f4f52bae76dd02/chall.c) - [chall.h](https://gist.github.com/YangSeungWon/3de1311c1e03195577f4f52bae76dd02/chall.h) - [main.c](https://gist.github.com/YangSeungWon/3de1311c1e03195577f4f52bae76dd02/main.c) - [chall](https://gist.github.com/YangSeungWon/3de1311c1e03195577f4f52bae76dd02/chall) - [sol.py](https://gist.github.com/YangSeungWon/3de1311c1e03195577f4f52bae76dd02/sol.py) Attachments are uploaded on [gist](https://gist.github.com/YangSeungWon/3de1311c1e03195577f4f52bae76dd02). ## Challenge https://challs.m0lecon.it:8005/ ![](https://i.imgur.com/vHu8V9E.png) When each button is pressed, review('*what you pressed*') is called. If it is long pressed, review('-') is also called. ## Solution ### Make ELF binary file in order to analyze in IDA $ ./wasm2c chall.wasm --no-debug-names -o chall.c Modified address of `wasm-rt.h` in `chall.h` to absolute path. Made `main.c` file to compile. ```c:main.c=1 int main(int argc, char* argv[]){ return 0; } ``` $ gcc chall.c ~/tools/wabt/wasm2c/wasm-rt-impl.c main.c -o chall now we have ELF binary file. --- ### Static Analysis pseudo code ```c:pseudocode= int data[98] = { 0x2a, 0x39, 0x67, 0x7e, 0x71, 0x2d, 0x21, 0x21, 0x72, 0x43, 0x41, 0x3a, 0x09, 0x0c, 0x04, 0x05, 0x52, 0x42, 0x40, 0x19, 0x0a, 0x77, 0x51, 0x42, 0x05, 0x23, 0x36, 0x5b, 0x0c, 0x67, 0x66, 0x22, 0x00, 0x4b, 0x27, 0x38, 0x47, 0x72, 0x6e, 0x5b, 0x75, 0x2b, 0x2c, 0x32, 0x5e, 0x53, 0x47, 0x5a, 0x22, 0x70, 0x74, 0x6d, 0x7b, 0x00, 0x77, 0x68, 0x61, 0x74, 0x27, 0x73, 0x20, 0x74, 0x68, 0x69, 0x73, 0x3f, 0x00, 0x7a, 0x7a, 0x7a, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x68, 0x78, 0x20, 0x2e, 0x2e, 0x2e, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x2e, 0x2e, 0x2e, 0x00, 0x2a, }; int cnt = 0; char f5(char arg){ cnt++; data[97] = arg ^ data[cnt] ^ data[97]; return data[97]; } status review(char input){ char res = f5(input); if(cnt-1 < 4){ if(data[48+cnt] == res){ return keepgoing; }else{ data[97] = 0x2a; cnt = 0; return fail; } } if(res > 0x7f){ data[97] = 0x2a; cnt = 0; return fail; } if(cnt == 47){ if(res == '}'){ return success; } else{ return fail; } } return keepgoing; } ``` --- ### Brute Forcing...? I made python code that do brute force... but we can know if these notes are right when all 48 notes are set. So we can know first 4 notes only: CCGG ### Google knows everything ![](https://i.imgur.com/z2MZ4eL.png) WOW! so the answer is ... `ccggaag-ffeeddc-ggffeed-ggffeed-ccggaag-ffeeddc-` ```py:sol.py= data = [0x2a, 0x39, 0x67, 0x7e, 0x71, 0x2d, 0x21, 0x21, 0x72, 0x43, 0x41, 0x3a, 0x09, 0x0c, 0x04, 0x05, 0x52, 0x42, 0x40, 0x19, 0x0a, 0x77, 0x51, 0x42, 0x05, 0x23, 0x36, 0x5b, 0x0c, 0x67, 0x66, 0x22, 0x00, 0x4b, 0x27, 0x38, 0x47, 0x72, 0x6e, 0x5b, 0x75, 0x2b, 0x2c, 0x32, 0x5e, 0x53, 0x47, 0x5a, 0x22, 0x70, 0x74, 0x6d, 0x7b, 0x00, 0x77, 0x68, 0x61, 0x74, 0x27, 0x73, 0x20, 0x74, 0x68, 0x69, 0x73, 0x3f, 0x00, 0x7a, 0x7a, 0x7a, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x68, 0x78, 0x20, 0x2e, 0x2e, 0x2e, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x2e, 0x2e, 0x2e, 0x00, 0x2a] cand = "cdefgab-" cnt = 0 def f5(arg): global cnt cnt += 1; data[97] = ord(arg) ^ data[cnt] ^ data[97] return data[97] def review(pressed): cnt_ = cnt res = f5(pressed) if cnt_ < 4: if data[49+cnt_] == res: return res else: return False if cnt_ == 47: if res == ord('}'): return res else: return False return res flag = "" for note in "ccggaag-ffeeddc-ggffeed-ggffeed-ccggaag-ffeeddc-": res = review(note) flag += chr(res) print(flag) ``` output : `ptm{7w1nKl3_7W1NkL3_My_w3b_574r_w3lL_Pl4y3d_hKr}`