Uzeil Moderator Reputation: 6
Joined: 21 Oct 2006 Posts: 2411
|
Posted: Sun Mar 18, 2007 4:39 am Post subject: [Assembly] Basic Obfuscation |
|
|
This is a small script that would hide something... pretty well to the person not binary experienced
Get ready for a 'crazy' script. Don't dismiss this just because you don't understand stuff yet. I give brief descriptions of the operators and show them on the binary level so you don't have to learn to convert just yet (although you can go learn in my other top 'Learn ASM and voice your opinions')
Code: | push eax
xor eax, dword ptr [esp]
and dword ptr [esp],eax
pop ebx
xor bl,87
xor bh,bl
or ax,b887
xor al,50
xor ah,2
shl eax,12
xor bx,78a
push eax
xor dword ptr [esp],ebx
ret |
In the end, it simply jumps. read on.
Code: | push eax
xor eax, dword ptr [esp]
and dword ptr [esp],eax
pop ebx |
This just clears eax and ebx. I explaned in page 3 (or top of page 4 maybe)
Code: | xor bl,87
xor bh,bl | if you xor a register that is 0 by another value, then it is going to now hold that value. in xor, anything that lines up gets unset.
Code: | 0000 0000 <-bl = 00 (bl is the last two digits of EBX)
1000 0111 <- 87
__________ <- result line
1000 0111 <- BL is now 87 |
Then it does the same logic to BH (the two digits above BL. if EAX is 12345678, BH is 56.) In this case, BH is 0 (because all of ebx was 0, and all we did just now was effect BL, which is not in BH)
so, xor them. Code: | 0000 0000 <- BH
1000 0111 <- BL (87)
__________
1000 0111 <- BH is now 87. |
Therefore, EBX is now 00008787 Let's continue on with EAX . Which is currently 0.
Ok. AX is the last 4 digits of EAX. EAX came in as 0, and then was OR'd by b887. With the OR operator, if anything is set on that bit of either value, then the resulting bit is set.
so lets OR them. Code: | 0000 0000 0000 0000 <- AX.
1011 1000 1000 0111 <- b887
___________________
1011 1000 1000 0111 <- AX is now b887, which means EAX is 0000b887. |
next lines. Ok. xor al (which is 87. the last two digits of EAX, remember?) by 50. Lets line that binary up
Code: | 1000 0111 <-al (87)
0101 0000 <- 50
__________
1101 0111 <- B7. Therefore, al is now B7, which means EAX is now 0000b8d7 |
Then xor AH, 2. AH is b8 (see those two digits?)
Code: | 1011 1000 <-AH (b8)
0000 0010 <- 2
__________
1011 1010 <- BA :) AH is now BA, which means EAX is now 0000bad7 |
next line
Ok. This is where math comes in (even though I'll bring this to the binary level for you.) Shl means Shift Left. the syntax in Intel format is Code: | shiftleft destination,count | It takes the destination on the binary level and shifts is left [count] times. Here, we are shifting it left 12 times. Well if you are observant and have good knowledge of binary->bits->'nibbles'(4 bits)->bytes, you'll notice that 12 is divisible by 4. Every 4 bits is one digit of hex (nibble), so you know that you technically don't even need to look at the binary level.
in other words, if you divide it out, you already know that it is shifting left (12 / 4 =) 3 digits. Therefore, it would become 0bad7000. However, I'll pull up the binary level for you.
Code: | 0000 0000 0000 0000 1011 1010 1101 0111 <- 0000bad7
0000 0000 0000 0001 0111 0101 1010 1110 <- first shift.
0000 0000 0000 0010 1110 1011 0101 1100 <- second shift.
0000 0000 0000 0101 1101 0110 1011 1000 <- third shift
0000 0000 0000 1011 1010 1101 0111 0000 <- fourth
0000 0000 0001 0111 0101 1010 1110 0000 <- fifth
0000 0000 0010 1110 1011 0101 1100 0000 <- sixth
0000 0000 0101 1101 0110 1011 1000 0000 <- seventh
0000 0000 1011 1010 1101 0111 0000 0000 <- eighth
0000 0001 0111 0101 1010 1110 0000 0000 <- ninth
0000 0010 1110 1011 0101 1100 0000 0000 <- tenth
0000 0101 1101 0110 1011 1000 0000 0000 <- eleventh
0000 1011 1010 1101 0111 0000 0000 0000 <- 12 ! :)
_______________________________
0 b a d 7 0 0 0 |
What did I tell ya?
Ok, now lets continue. EAX is 0bad7000 as I just showed you, and if you look above, EBX is 00008787. which means BX is 8787
Binary time!
Code: | 1000 0111 1000 0111 <- BX (8787)
0000 0111 1000 1010 <- 78a
___________________
1000 0000 0000 1101 <- BX is now 800D |
Which means EBX is now 0000800d and remember from above: EAX is 0bad7000 (I wonder if anyone caught on yet ) Continue.
push eax, aka give space on the stack and make [esp] whatever eax holds. which means [esp] is now 0bad7000.
Code: | xor dword ptr [esp],ebx | Binary time [esp] as I just said is 0bad7000 and EBX is 0000800d
Code: | 0000 1011 1010 1101 0111 0000 0000 0000 <- [esp] (0bad7000)
0000 0000 0000 0000 1000 0000 0000 1101 <- EBX (0000800d)
________________________________________-
0000 1011 1010 1101 1111 0000 0000 1101 <- [esp] is now 0badf00d :) |
Haha, so now [esp] is badf00d. The only thing left is 'ret'.
Found it Ok. The return function basically just says 'pop eip'. ret has more abilities than that, but you get the idea.
If you were around before this whole CRC Bypass thing, you would know that EIP (extended insturction pointer) holds where to go for the next instruction. For instance:
if at address 1234566, the opcode was nop (only one byte), then EIP at that point would hold 1234567. Then lets say 1234567 was add [eax],al (blank code / 2 bytes), EIP would hold 1234569.
By making EIP (the next address) be whatever the top of the stack holds, it basically is just saying 'pop off of the stack, then jump to whatever was on the top of the stack.'
just jump to the top of the stack. which is badf00d. The script jumps to badf00d. That is the answer (<- simplest way to put it)
_________________
|
|