-3

Goal I am trying a simple shellcode exercise - call "OutputDebugStringA" on a remote process using CreateRemoteThread that will activate a shellcode - this exercise is without dll injection!

problem I dont know the address of "OutputDebugStringA" at the remote process, only at the local process.

What I have been trying so far

int main() {
char ShellCode[] = "\x48\x8d\x0c\x25\x10\x9c\x8c\x4c\xff\x14\x25\x00\x01\x8d\x4c";
/*
* Get process handle passing in the process ID.
*/
int32_t nProcID = 21440;
const HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, nProcID);
if (NULL == hProcess) {
    printf("Error: the specified process couldn't be found.\n");
}

const LPVOID arg = (LPVOID)VirtualAllocEx(hProcess, NULL, sizeof(ShellCode), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (NULL == arg) {
    int32_t nLastErrorCode = GetLastError();
    printf("Error: the memory could not be allocated inside the chosen process. Error code - %d.\n", nLastErrorCode);
}

const int32_t nBytesWritten = WriteProcessMemory(hProcess, arg, ShellCode, sizeof(ShellCode), NULL);
if (0 == nBytesWritten) {
    int32_t nLastErrorCode = GetLastError();
    printf("Error: there was no bytes written to the process's address space. Error code - %d.\n", nLastErrorCode);
}

const HANDLE hThreadID = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)arg , NULL, NULL, NULL);
if (NULL == hThreadID) {
    int32_t nLastErrorCode = GetLastError();
    printf("Error: the remote thread could not be created. Error code - %d.\n", nLastErrorCode);
}
else {
    printf("Success: the remote thread was successfully created.\n");
}

/*
* Close the handle to the process, because we've already injected the DLL.
*/
CloseHandle(hProcess);
getchar();

return 0;

}

What I tried Dissemble OutputDebugStringA picture1 then convert it to shellcode online and then call my code with the new shellcode. But the remote proccess is not familiar with these addresses.

ohad
  • 7
  • 6
  • That is not "shellcode" at all. Simply create a DLL with the OutputDebugString() call, LoadLibrary() to inject it. – Hans Passant Nov 20 '18 at 16:06
  • there are two exercises. The first one was to inject using a dll. In the second one you are supposed only to inject a shellcode by allocating memory at the remote process, write the shellcode and then call it using the CreatRemoteThread function – ohad Nov 20 '18 at 16:08
  • 1
    Enumerate the modules of the remote process. Find the module containing the function. Read that module's PE headers to work out where the entry point is. – David Heffernan Nov 20 '18 at 16:24
  • You need the information about how OutputDebugString() was load in the remote process, then inject codes call to its true address. – tunglt Nov 20 '18 at 16:25
  • No need to parse the PE headers. Figure out the offset of OutputDebugStringA relative to the module start address (HMODULE) in the current process, then apply the same offset in the target process. – Seva Alekseyev Nov 20 '18 at 16:28
  • 2
    @sev: Won't work, if you are running a 32-bit process and want to inject code into a 64-bit process. – IInspectable Nov 20 '18 at 16:41
  • Or vice versa. Right. – Seva Alekseyev Nov 20 '18 at 17:19
  • They are both 64 bit – ohad Nov 20 '18 at 17:34

1 Answers1

-1

If the only thing you want to know is the address of OutputDebugStringA, (assuming that your shellcode does work), it is the same as the current process. So you can get it by doing LPVOID function_addr = reinterpret_cast<LPVOID>(GetProcAddress(GetModuleHandleA("kernel32.dll"), "OutputDebugStringA")); Then you can use function_addr as you want.

Because kernel32.dll has the same base address in every process, the relative virtual address will be the same, and thus, the address will be the same.

Arush Agarampur
  • 1,340
  • 7
  • 20
  • Not correct in general. The base address of *kenel32.dll* is not the same in processes with different bitness. Since the question doesn't limit itself to processes of the same bitness, this proposed answer is only a partial solution. – IInspectable Dec 06 '18 at 08:48
  • In windows, the base address of ntdll.dll and kernel32.dll are always the same. – Arush Agarampur Dec 06 '18 at 15:49
  • `0x00007FFFBC300000` and `0x748A0000` are undoubtedly not the same address. The former is the base address of kernel32.dll in a 64-bit process, the latter in a 32-bit process. On my system. Today. – IInspectable Dec 06 '18 at 19:38
  • You are correct. I was assuming the architectures would be the same. – Arush Agarampur Dec 07 '18 at 05:32