# DEF CON CTF Qualifier 2019 - nodb >###### tags: `wasm` >[name=whysw@PLUS] ## Attachments - problem - [index.html](https://gist.github.com/YangSeungWon/5af37d55f65b44e7ddb027f84897956f#file-index-html) - [wasm.js](https://gist.github.com/YangSeungWon/5af37d55f65b44e7ddb027f84897956f#file-wasm-js) - [wasm.wasm](https://gist.github.com/YangSeungWon/5af37d55f65b44e7ddb027f84897956f#file-wasm-wasm) - writeup - [wasm.wat](https://gist.github.com/YangSeungWon/5af37d55f65b44e7ddb027f84897956f#file-wasm-wat) - [wasm_57.wat](https://gist.github.com/YangSeungWon/5af37d55f65b44e7ddb027f84897956f#file-wasm_57-wat) - [wasm_57.wasm](https://gist.github.com/YangSeungWon/5af37d55f65b44e7ddb027f84897956f#file-wasm_57-wasm) Attachments are uploaded on [gist](https://gist.github.com/YangSeungWon/5af37d55f65b44e7ddb027f84897956f). If you want to run payload, you need to change `var wasmBinaryFile = 'wasm.wasm';` to `var wasmBinaryFile = 'wasm_57.wasm'` in `function integrateWasmJS()`, in wasm.js file. ## Challenge ![](https://i.imgur.com/T3lpCPY.png) When you press the button **Submit**, the value in the password field goes to _authenticate function of WASM. ![](https://i.imgur.com/rM1izQM.png) ## Solution ### JEB demo WASM can be decompiled using JEB > v3.0.0. There is many limitations in demo version, but I can find out what _authenticate function does. ![](https://i.imgur.com/TNbzNgO.png) So the length of the flag must be 69. And variable `v8` increases if v14 is 0. In the end, `v8` must be 69 to return `success`, so `v8` contains the information about how many characters are same with the flag. So we can use brute force to get the flag, if we know v8 for every input. --- ### patch WASM using WAT #### wasm2wat Using wasm2wat in [wabt](https://github.com/WebAssembly/wabt), you can get .WAT file(webassembly text file) ```bash ~/tools/wabt/build/wasm2wat wasm.wasm > wasm.wat ``` #### patch _authenticate function _authenticate function is func25. (we can know it through dynamic debugging) At the end of the _authenticate function, we can see what we analyzed in decompiled source. ```csharp:wasm.wat=448 //this is not csharp file, but for highlight :) local.get 58 local.set 49 local.get 49 // this might be v8 i32.const 1 // because 1 is added i32.add local.set 50 local.get 50 local.set 58 br 1 (;@1;) end end // at the end of the for loop, local.get 57 local.set 51 local.get 51 i32.const 69 // v8 is XORed with 69 i32.xor local.set 52 local.get 52 i32.const 0 i32.ne // and tested if they are same. local.set 53 local.get 53 if ;; label = @1 // if v8 != 69 i32.const 1245 // return 1245 local.set 1 local.get 1 local.set 54 local.get 61 global.set 12 local.get 54 return else // if v8 == 69 i32.const 1237 // return 1237 local.set 1 local.get 1 local.set 54 local.get 61 global.set 12 local.get 54 return end unreachable i32.const 0 return) ``` so we can patch it to return v8 no matter v8 == 69 or not. ```csharp:wasm_57.wat=470 if ;; label = @1 local.get 57 // local variable 57 has the value of v8. check above :) local.set 1 local.get 1 local.set 54 local.get 61 global.set 12 local.get 54 return else local.get 57 local.set 1 local.get 1 local.set 54 local.get 61 global.set 12 local.get 54 return end unreachable i32.const 0 return) ``` #### wat2wasm Using wat2wasm (also) in [wabt](https://github.com/WebAssembly/wabt), you can get .WASM file again. ```bash ~/tools/wabt/build/wat2wasm wasm_57.wat ``` It generates wasm_57.wasm file. --- ### Brute Force ```javascript:sol.js= flag="" for(i=0; i<69; i++){ for(j=32; j<128; j++){ trial = flag + String.fromCharCode(j); trial = trial.padEnd(69,'|'); res = _authenticate(allocate(intArrayFromString(trial),'i8',ALLOC_NORMAL)); if(res == i+1){ flag += String.fromCharCode(j); break; } } } console.log(flag); ``` output : `OOO{ifthereisnodataontheserverthereisnodatabreachproblemsolvedkthxbb}`