Search code examples
c++windowswinapishellcode

call windows API function using a shellcode


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.


Solution

  • 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.