Rizin
unix-like reverse engineering framework and cli tools
libbochs.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2016 SkUaTeR <skuater@hotmail.com>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include "libbochs.h"
5 
6 static char *lpTmpBuffer; //[0x2800u];
7 
8 #define SIZE_BUF 0x5800 * 2
9 
10 #if __WINDOWS__
11 #ifdef _MSC_VER
12 #pragma comment(lib, "user32.lib")
13 #endif
14 int RunRemoteThread_(libbochs_t *b, const ut8 *lpBuffer, ut32 dwSize, int a4, ut32 *lpExitCode) {
15  LPVOID pProcessMemory;
16  HANDLE hInjectThread = NULL;
17  int result = 0;
18  SIZE_T NumberOfBytesWritten;
19 
20  pProcessMemory = VirtualAllocEx(b->processInfo.hProcess, 0, dwSize, 0x1000u, 0x40u);
21  if (pProcessMemory) {
22  if (WriteProcessMemory(b->processInfo.hProcess, pProcessMemory, lpBuffer, dwSize, &NumberOfBytesWritten)) {
23  hInjectThread = CreateRemoteThread(b->processInfo.hProcess, 0, 0, pProcessMemory, 0, 0, 0);
24  if (hInjectThread) {
25  if (!WaitForSingleObject(hInjectThread, 0xFFFFFFFF) && (!a4 || ReadProcessMemory(b->processInfo.hProcess, pProcessMemory, (PVOID)lpBuffer, dwSize, &NumberOfBytesWritten))) {
26  if (lpExitCode)
27  GetExitCodeThread(hInjectThread, (PDWORD)lpExitCode);
28  result = 1;
29  }
30  }
31  }
32  VirtualFreeEx(b->processInfo.hProcess, pProcessMemory, 0, 0x8000u);
33  if (hInjectThread)
34  CloseHandle(hInjectThread);
35  }
36  return result;
37 }
38 #endif
39 
41  memset(b->data, 0, SIZE_BUF);
42  b->punteroBuffer = 0;
43 }
44 
46 #if __WINDOWS__
47  HMODULE hKernel;
48  unsigned int ExitCode;
49  DWORD apiOffset = 0;
50  char buffer[] = {
51  0x68, 0x00, 0x00, 0x00, 0x00, // push 0
52  0x68, 0x00, 0x00, 0x00, 0x00, // push 0
53  0xE8, 0x00, 0x00, 0x00, 0x00, // call $
54  0x83, 0x04, 0x24, 0x0A, // add [esp], 0A
55  0x68, 0x30, 0x30, 0x30, 0x30, // push GenerateConsoleCtrlEvent
56  0xC3, // retn
57  0xC2, 0x04, 0x00, // retn 4
58  0xeb, 0xfe // jmp $
59  };
60  hKernel = GetModuleHandle(TEXT("kernel32"));
61  apiOffset = (DWORD)GetProcAddress(hKernel, "GenerateConsoleCtrlEvent");
62  *((DWORD *)&buffer[20]) = apiOffset;
63  ExitCode = RunRemoteThread_(b, (const ut8 *)&buffer, 0x1Eu, 0, &ExitCode) && ExitCode;
64  return ExitCode;
65 #else
66  return 0;
67 #endif
68 }
69 
71 #if __WINDOWS__
72  int times = 100;
73  DWORD dwRead, aval, leftm;
75  do {
76  while (PeekNamedPipe(b->hReadPipeIn, NULL, 0, NULL, &aval, &leftm)) {
77  if (aval < 0)
78  break;
79  if (!ReadFile(b->hReadPipeIn, &b->data[b->punteroBuffer], SIZE_BUF, &dwRead, 0)) {
80  lprintf("bochs_wait: ERROR reading from pipe.\n\n");
81  return false;
82  }
83  if (dwRead)
84  b->punteroBuffer += dwRead;
85  }
86  if (strstr(b->data, "<bochs:")) {
87  break;
88  }
89  Sleep(5);
90  } while (--times);
91  return true;
92 #else
93  int flags, n;
95  flags = fcntl(b->hReadPipeIn, F_GETFL, 0);
96  (void)fcntl(b->hReadPipeIn, (flags | O_NONBLOCK));
97  for (;;) {
98  n = read(b->hReadPipeIn, lpTmpBuffer, SIZE_BUF - 1);
99  if (n > 0) {
100  lpTmpBuffer[n] = 0;
101  if (b->punteroBuffer + n >= SIZE_BUF - 1) {
103  }
104  // XXX overflow here
105  memcpy(b->data + b->punteroBuffer, lpTmpBuffer, n + 1);
106  b->punteroBuffer += n;
107  if (strstr(&b->data[0], "<bochs:")) {
108  break;
109  }
110  }
111  }
112  (void)fcntl(b->hReadPipeIn, (flags | ~O_NONBLOCK));
113  return true;
114 #endif
115 }
116 
117 void bochs_send_cmd(libbochs_t *b, const char *cmd, bool bWait) {
118  char *cmdbuff = rz_str_newf("%s\n", cmd);
120  size_t cmdlen = strlen(cmdbuff);
121 #if __WINDOWS__
122  DWORD dwWritten;
123  if (!WriteFile(b->hWritePipeOut, cmdbuff, cmdlen, &dwWritten, NULL)) {
124 #else
125  if (write(b->hWritePipeOut, cmdbuff, cmdlen) != cmdlen) {
126 #endif
127  eprintf("boch_send_cmd failed\n");
128  goto beach;
129  }
130  if (bWait)
131  bochs_wait(b);
132 beach:
133  free(cmdbuff);
134 }
135 
137  char buff[128];
138  char *data;
139  int lenRec = 0, i = 0, ini = 0, fin = 0, pbuf = 0, totalread = 0;
140  totalread = (count > SIZE_BUF / 3) ? SIZE_BUF / 3 : count;
141  snprintf(buff, sizeof(buff), "xp /%imb 0x%016" PFMT64x "", totalread, addr);
142  bochs_send_cmd(b, buff, true);
143  data = strstr(&b->data[0], "[bochs]:");
144  if (!data) {
145  eprintf("bochs_read: Can't find bochs prompt\n");
146  return false;
147  }
148  lenRec = strlen(data);
149  if (!strncmp(data, "[bochs]:", 8)) {
150  i += 10; // seek to next line
151  do {
152  while (data[i] != 0 && data[i] != ':' && i < lenRec) // find :
153  i++;
154  ini = ++i;
155  while (data[i] != 0 && data[i] != '\n' && data[i] != 0xd && i < lenRec) // find newline
156  i++;
157  fin = i++;
158  data[fin] = 0;
159  if (data[i] == '<')
160  break;
161  pbuf += rz_hex_str2bin(&data[ini], &buf[pbuf]);
162  i++; // next line
163  } while (data[i] != '<' && i < lenRec);
164  }
165  return 0;
166 }
167 
169  b->isRunning = false;
170 #if __WINDOWS__
171  CloseHandle(b->hReadPipeIn);
172  CloseHandle(b->hReadPipeOut);
173  CloseHandle(b->hWritePipeIn);
174  CloseHandle(b->hWritePipeOut);
175  CloseHandle(b->ghWriteEvent);
176  TerminateProcess(b->processInfo.hProcess, 0);
177  free(b->data);
178  free(lpTmpBuffer);
179 #else
180  close(b->hReadPipeIn);
181  close(b->hWritePipeOut);
182  kill(b->pid, SIGKILL);
183  RZ_FREE(b->data);
185 #endif
186 }
187 
188 bool bochs_open(libbochs_t *b, const char *pathBochs, const char *pathConfig) {
189  bool result = false;
190 
191  b->data = malloc(SIZE_BUF);
192  if (!b->data) {
193  return false;
194  }
196  if (!lpTmpBuffer) {
197  RZ_FREE(b->data);
198  return false;
199  }
200 #if __WINDOWS__
201  struct _SECURITY_ATTRIBUTES PipeAttributes;
202  char commandline[1024];
203  PipeAttributes.nLength = 12;
204  PipeAttributes.bInheritHandle = 1;
205  PipeAttributes.lpSecurityDescriptor = 0;
206  //
207  if (CreatePipe(&b->hReadPipeIn, &b->hReadPipeOut, &PipeAttributes, SIZE_BUF) &&
208  CreatePipe(&b->hWritePipeIn, &b->hWritePipeOut, &PipeAttributes, SIZE_BUF)) {
209  LPTSTR commandline_;
210 
211  memset(&b->info, 0, sizeof(STARTUPINFOA));
212  memset(&b->processInfo, 0, sizeof(PROCESS_INFORMATION));
213  b->info.cb = sizeof(STARTUPINFOA);
214  b->info.hStdError = b->hReadPipeOut;
215  b->info.hStdOutput = b->hReadPipeOut;
216  b->info.hStdInput = b->hWritePipeIn;
217  b->info.dwFlags |= STARTF_USESTDHANDLES;
218  snprintf(commandline, sizeof(commandline), "\"%s\" -f \"%s\" -q ", pathBochs, pathConfig);
219  lprintf("*** Creating process: %s\n", commandline);
220  commandline_ = rz_sys_conv_utf8_to_win(commandline);
221  if (CreateProcess(NULL, commandline_, NULL, NULL, TRUE, CREATE_NEW_CONSOLE,
222  NULL, NULL, &b->info, &b->processInfo)) {
223  lprintf("Process created\n");
224  WaitForInputIdle(b->processInfo.hProcess, INFINITE);
225  lprintf("Initialized input\n");
226  b->isRunning = true;
228  eprintf("Waiting for bochs...\n");
229  if (bochs_wait(b)) {
230  eprintf("Ready.\n");
231  result = true;
232  } else {
233  bochs_close(b);
234  }
235  }
236  free(commandline_);
237  }
238 #else
239 #define PIPE_READ 0
240 #define PIPE_WRITE 1
241  int aStdinPipe[2];
242  int aStdoutPipe[2];
243  int nChild;
244 
245  if (rz_sys_pipe(aStdinPipe, true) < 0) {
246  eprintf("Error: allocating pipe for child input redirect");
247  return false;
248  }
249  if (rz_sys_pipe(aStdoutPipe, true) < 0) {
250  rz_sys_pipe_close(aStdinPipe[PIPE_READ]);
251  rz_sys_pipe_close(aStdinPipe[PIPE_WRITE]);
252  eprintf("Error: allocating pipe for child output redirect");
253  return false;
254  }
255 
256  nChild = fork();
257  if (0 == nChild) {
258  // redirect stdin
259  if (dup2(aStdinPipe[PIPE_READ], STDIN_FILENO) == -1) {
260  eprintf("Error: redirecting stdin");
261  return false;
262  }
263 
264  // redirect stdout
265  if (dup2(aStdoutPipe[PIPE_WRITE], STDOUT_FILENO) == -1) {
266  eprintf("Error: redirecting stdout");
267  return false;
268  }
269 
270  // redirect stderr
271  if (dup2(aStdoutPipe[PIPE_WRITE], STDERR_FILENO) == -1) {
272  eprintf("Error: redirecting stderr");
273  return false;
274  }
275 
276  rz_sys_pipe_close(aStdinPipe[PIPE_READ]);
277  rz_sys_pipe_close(aStdinPipe[PIPE_WRITE]);
278  rz_sys_pipe_close(aStdoutPipe[PIPE_READ]);
279  rz_sys_pipe_close(aStdoutPipe[PIPE_WRITE]);
280  (void)rz_sys_execl(pathBochs, pathBochs, "-q", "-f", pathConfig, NULL);
281  perror("execl");
282  exit(1);
283  } else if (nChild > 0) {
284  rz_sys_pipe_close(aStdinPipe[PIPE_READ]);
285  rz_sys_pipe_close(aStdoutPipe[PIPE_WRITE]);
286 
287  if (read(aStdoutPipe[PIPE_READ], lpTmpBuffer, 1) != 1) {
288  eprintf("boch_open failed");
289  bochs_close(b);
290  } else {
291  b->hReadPipeIn = aStdoutPipe[PIPE_READ];
292  b->hWritePipeOut = aStdinPipe[PIPE_WRITE];
293  b->isRunning = true;
295  eprintf("Waiting for bochs...\n");
296  if (bochs_wait(b)) {
297  eprintf("Ready.\n");
298  b->pid = nChild;
299  result = true;
300  } else {
301  bochs_close(b);
302  }
303  }
304  } else {
305  perror("pipe");
306  // failed to create child
307  rz_sys_pipe_close(aStdinPipe[PIPE_READ]);
308  rz_sys_pipe_close(aStdinPipe[PIPE_WRITE]);
309  rz_sys_pipe_close(aStdoutPipe[PIPE_READ]);
310  rz_sys_pipe_close(aStdoutPipe[PIPE_WRITE]);
311  }
312 #endif
313  return result;
314 }
lzma_index ** i
Definition: index.h:629
#define SIGKILL
#define NULL
Definition: cris-opc.c:27
static static fork write
Definition: sflib.h:33
static static fork const void static count close
Definition: sflib.h:33
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags cmd
Definition: sflib.h:79
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags fcntl
Definition: sflib.h:79
uint32_t ut32
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void * buf
Definition: ioapi.h:138
snprintf
Definition: kernel.h:364
uint8_t ut8
Definition: lh5801.h:11
#define SIZE_BUF
Definition: libbochs.c:8
int bochs_read(libbochs_t *b, ut64 addr, int count, ut8 *buf)
Definition: libbochs.c:136
#define PIPE_READ
bool bochs_wait(libbochs_t *b)
Definition: libbochs.c:70
static char * lpTmpBuffer
Definition: libbochs.c:6
bool bochs_open(libbochs_t *b, const char *pathBochs, const char *pathConfig)
Definition: libbochs.c:188
void bochs_send_cmd(libbochs_t *b, const char *cmd, bool bWait)
Definition: libbochs.c:117
#define PIPE_WRITE
void bochs_close(libbochs_t *b)
Definition: libbochs.c:168
void bochs_reset_buffer(libbochs_t *b)
Definition: libbochs.c:40
bool bochs_cmd_stop(libbochs_t *b)
Definition: libbochs.c:45
#define lprintf(x, y...)
Definition: libbochs.h:64
return memset(p, 0, total)
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
void * malloc(size_t size)
Definition: malloc.c:123
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig const char static mode static oldfd times
Definition: sflib.h:70
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc kill
Definition: sflib.h:64
static static fork const void static count static fd const char static mode const char static pathname const char static path const char static dev const char static group static getpid static getuid void void static data static pause const char static mode static sync const char const char static newpath const char static pathname unsigned long static filedes void static end_data_segment static handler static getegid char static len static pgid const char static path dup2
Definition: sflib.h:94
int n
Definition: mipsasm.c:19
#define TRUE
Definition: mybfd.h:103
#define eprintf(x, y...)
Definition: rlcc.c:7
RZ_API int rz_hex_str2bin(const char *in, ut8 *out)
Convert an input string in into the binary form in out.
Definition: hex.c:444
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API int rz_sys_execl(const char *pathname, const char *arg,...)
Definition: sys.c:1575
RZ_API int rz_sys_pipe(int pipefd[2], bool close_on_exec)
Definition: sys.c:1458
RZ_API int rz_sys_pipe_close(int fd)
Definition: sys.c:1462
#define RZ_FREE(x)
Definition: rz_types.h:369
#define PFMT64x
Definition: rz_types.h:393
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123
#define F_GETFL
Definition: sftypes.h:506
#define O_NONBLOCK
Definition: sftypes.h:494
#define b(i)
Definition: sha256.c:42
Definition: buffer.h:15
#define STDOUT_FILENO
Definition: private.h:41
#define STDERR_FILENO
Definition: private.h:45
#define STDIN_FILENO
Definition: private.h:37
DWORD PDWORD
DWORD * HANDLE
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
PVOID
DWORD
static int addr
Definition: z80asm.c:58
int read(izstream &zs, T *x, Items items)
Definition: zstream.h:115