same code as last time, but this time a bit more proper. This time, instead of replacing part of the program, I'd like to run something in the context of that program, lets say.... it has a file open and I want to write to it at the same time... or.... it has permissions that I dont. (ever wonder how some programs can read the sam file while inside windows?) in this example, I have a small chunk of code I crafted by hand to make sure all static addresses were gone Lets learn some ASSEMBLY! Code: 003C0000 E8 00000000 CALL 003C0005 003C0005 5A POP EDX 003C0006 83C2 18 ADD EDX,18 003C0009 6A 00 PUSH 0 003C000B 52 PUSH EDX 003C000C 52 PUSH EDX 003C000D 6A 00 PUSH 0 003C000F B8 19D68876 MOV EAX,USER32.MessageBoxA 003C0014 FFD0 CALL EAX 003C0016 B8 543B7776 MOV EAX,kernel32.ExitProcess 003C001B FFD0 CALL EAX 003C001D 54 PUSH ESP 003C001E 65:73 74 JNB SHORT 003C0095 scary right? nah, just new. lets dig! ok, so This code wants to make a pop up messagebox saying "Test" with a title of "Test" So we store the string "Test" somewhere in our code (at the end, because we dont want the cpu to try to execute it LOL) but how do we referance it? vista's memory is randomly silly... well... if we know where we are when we start executing the code, we can do a trick I made up. when you call a function, the place you need to return to after the function is called is stored on the stack... so if we call a fake function, RIGHT UNDERNEATH US, we have the current position, on the stack Thats the first line Code: 003C0000 E8 00000000 CALL 003C0005 now, looking at that line, it looks hard coded (YO DUDE ITS JUST CALLING THE ADDRESS 003c0005) actually, thats just ollydbg being awsome, how a call works, is relative. E8=call, the next 4 bytes are the DISTANCE TO THE function. because the function is the next line, its 00000000 so then we need to get the address off the stack, so we pop it off to edx Code: 003C0005 5A POP EDX now we need to find our string, because our code has a constant length (we coded it lol) so we add 18 (in hex) 24 (in dec) to it Code: 003C0006 83C2 18 ADD EDX,18 now, we start pushing arguments MessageBoxA says it wants 4 http://msdn.microsoft.com/en-us/library/ms645505(VS.85).aspx remember arguments are pushed backwards so we start with the last utype: MB_OK The message box contains one push button: OK. This is the default. so we push 0 Code: 003C0009 6A 00 PUSH 0 Then lpText and lpCaption, so we push edx twice (because its pointing to "Test") Code: 003C000B 52 PUSH EDX 003C000C 52 PUSH EDX Then hWnd [in] Handle to the owner window of the message box to be created. If this parameter is NULL, the message box has no owner window. So we push 0 again Code: 003C000D 6A 00 PUSH 0 Now we push the address to MessagBoxA (since we dont know this yet, we put in FFFFFFFF for the address for now, and in our c++ we will replace it once we find it) Code: 003C000F B8 19D68876 MOV EAX,USER32.MessageBoxA Then we call MessageBoxA, which is now in eax Code: 003C0014 FFD0 CALL EAX same thing for ExitProcess Code: 003C0016 B8 543B7776 MOV EAX,kernel32.ExitProcess 003C001B FFD0 CALL EAX and now, what the heck is this? Code: 003C001D 54 PUSH ESP 003C001E 65:73 74 JNB SHORT 003C0095 lol its just Test T=54 e=65 s=73 t=74 http://asciitable.com yay! So now, we grab all the data from that assembly (in ollydbg, it shows the address, data, then assembly) so Code: 003C000F=address B8 19D68876=data MOV EAX,USER32.MessageBoxA=assembly so now heres the code! Code: //does messagebox and exit #include #include #include //Gets base address, cuz vista is tricky DWORD GetBaseAddress( DWORD dwPID, char* name ) { HANDLE hModuleSnap = INVALID_HANDLE_VALUE; MODULEENTRY32 me32; hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID ); if( hModuleSnap == INVALID_HANDLE_VALUE ) { printf( "CreateToolhelp32Snapshot (of modules)" ); return( 0 ); } me32.dwSize = sizeof( MODULEENTRY32 ); if( !Module32First( hModuleSnap, &me32 ) ) { printf( "Module32First" ); CloseHandle( hModuleSnap ); return( 0 ); } do { if (strstr(me32.szModule,name)) { return((DWORD) me32.modBaseAddr); } } while( Module32Next( hModuleSnap, &me32 ) ); CloseHandle( hModuleSnap ); return( 1 ); } char hexToAscii(char first, char second) { char hex[5], *stop; sprintf(hex,"0x%c%c",first,second); return strtol(hex, &stop, 16); } int main( ) { HWND hWnd = FindWindow("Notepad", NULL); if(hWnd == NULL) { printf("Error cannot find window!\n"); } else { char address[10]; DWORD proc_id,base,kernel,msgbox,exit; GetWindowThreadProcessId(hWnd, &proc_id); base=GetBaseAddress(proc_id,"notepad.exe"); msgbox=(DWORD)GetProcAddress(GetModuleHandle("User32"), "MessageBoxA"); exit=(DWORD)GetProcAddress(GetModuleHandle("Kernel32"), "ExitProcess"); DWORD dwOldProt; HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, proc_id); if(!hProcess) { printf("Cannot open process!\n"); } else { unsigned char data[] = "\xE8\x00\x00\x00\x00\x5A\x83\xC2\x18\x6A\x00" "\x52\x52\x6A\x00\xB8\xFF\xFF\xFF\xFF\xFF\xD0\xB8\xFF\xFF\xFF\xFF\xFF" "\xD0\x54\x65\x73\x74"; DWORD dataSize = sizeof(data); printf("\n\nExit: %x MessageBoxA: %x\n\n",exit,msgbox); sprintf(address,"%x",msgbox); data[16]=hexToAscii(address[6],address[7]); data[17]=hexToAscii(address[4],address[5]); data[18]=hexToAscii(address[2],address[3]); data[19]=hexToAscii(address[0],address[1]); sprintf(address,"%x",exit); data[23]=hexToAscii(address[6],address[7]); data[24]=hexToAscii(address[4],address[5]); data[25]=hexToAscii(address[2],address[3]); data[26]=hexToAscii(address[0],address[1]); for(int i=0; i