mirror of
https://github.com/radareorg/radare2.git
synced 2024-12-11 15:04:23 +00:00
87724384d1
Besides an UAF has been fixed afecting only ELF
212 lines
5.2 KiB
C
212 lines
5.2 KiB
C
/* radare2 - LGPL - Copyright 2015 pancake */
|
|
|
|
#include "r_lib.h"
|
|
#include "r_core.h"
|
|
#include "r_lang.h"
|
|
#if __WINDOWS__
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
static int lang_pipe_run(RLang *lang, const char *code, int len);
|
|
static int lang_pipe_file(RLang *lang, const char *file) {
|
|
return lang_pipe_run (lang, file, -1);
|
|
}
|
|
|
|
#if __WINDOWS__
|
|
static HANDLE myCreateChildProcess(const char * szCmdline) {
|
|
PROCESS_INFORMATION piProcInfo;
|
|
STARTUPINFO siStartInfo;
|
|
BOOL bSuccess = FALSE;
|
|
ZeroMemory (&piProcInfo, sizeof (PROCESS_INFORMATION));
|
|
ZeroMemory (&siStartInfo, sizeof (STARTUPINFO));
|
|
siStartInfo.cb = sizeof (STARTUPINFO);
|
|
LPTSTR szCmdLine2 = strdup (szCmdline);
|
|
bSuccess = CreateProcess (NULL, szCmdLine2, NULL, NULL,
|
|
TRUE, 0, NULL, NULL, &siStartInfo, &piProcInfo);
|
|
free (szCmdLine2);
|
|
//CloseHandle (piProcInfo.hProcess);
|
|
//CloseHandle (piProcInfo.hThread);
|
|
return bSuccess? piProcInfo.hProcess: NULL;
|
|
}
|
|
static BOOL bStopThread = FALSE;
|
|
static HANDLE hPipeInOut = NULL;
|
|
static HANDLE hproc = NULL;
|
|
#define PIPE_BUF_SIZE 4096
|
|
DWORD WINAPI ThreadFunction(LPVOID lpParam) {
|
|
RLang * lang = lpParam;
|
|
CHAR buf[PIPE_BUF_SIZE];
|
|
BOOL bSuccess = FALSE;
|
|
int i, res = 0;
|
|
DWORD dwRead, dwWritten;
|
|
r_cons_break_push (NULL, NULL);
|
|
res = ConnectNamedPipe (hPipeInOut, NULL);
|
|
if (!res) {
|
|
eprintf ("ConnectNamedPipe failed\n");
|
|
return FALSE;
|
|
}
|
|
do {
|
|
if (r_cons_is_breaked ()) {
|
|
TerminateProcess(hproc,0);
|
|
break;
|
|
}
|
|
memset (buf, 0, PIPE_BUF_SIZE);
|
|
bSuccess = ReadFile (hPipeInOut, buf, PIPE_BUF_SIZE, &dwRead, NULL);
|
|
if (bStopThread)
|
|
break;
|
|
if (bSuccess && dwRead>0) {
|
|
buf[sizeof (buf)-1] = 0;
|
|
char *res = lang->cmd_str ((RCore*)lang->user, buf);
|
|
if (res) {
|
|
int res_len = strlen (res) + 1;
|
|
for (i = 0; i < res_len; i++) {
|
|
memset (buf, 0, PIPE_BUF_SIZE);
|
|
dwWritten = 0;
|
|
int writelen=res_len - i;
|
|
int rc = WriteFile (hPipeInOut, res + i, writelen>PIPE_BUF_SIZE?PIPE_BUF_SIZE:writelen, &dwWritten, 0);
|
|
if (bStopThread) {
|
|
free (res);
|
|
break;
|
|
}
|
|
if (!rc) {
|
|
eprintf ("WriteFile: failed 0x%x\n", (int)GetLastError());
|
|
}
|
|
if (dwWritten > 0) {
|
|
i += dwWritten - 1;
|
|
} else {
|
|
/* send null termination // chop */
|
|
eprintf ("w32-lang-pipe: 0x%x\n", (ut32)GetLastError ());
|
|
//WriteFile (hPipeInOut, "", 1, &dwWritten, NULL);
|
|
//break;
|
|
}
|
|
}
|
|
free (res);
|
|
} else {
|
|
WriteFile (hPipeInOut, "", 1, &dwWritten, NULL);
|
|
}
|
|
}
|
|
} while(!bStopThread);
|
|
r_cons_break_pop ();
|
|
return TRUE;
|
|
}
|
|
#else
|
|
static void env(const char *s, int f) {
|
|
char *a = r_str_newf ("%d", f);
|
|
r_sys_setenv (s, a);
|
|
// eprintf ("%s %s\n", s, a);
|
|
free (a);
|
|
}
|
|
#endif
|
|
|
|
static int lang_pipe_run(RLang *lang, const char *code, int len) {
|
|
#if __UNIX__
|
|
int safe_in = dup (0);
|
|
int child, ret;
|
|
int input[2];
|
|
int output[2];
|
|
|
|
pipe (input);
|
|
pipe (output);
|
|
|
|
env ("R2PIPE_IN", input[0]);
|
|
env ("R2PIPE_OUT", output[1]);
|
|
|
|
child = r_sys_fork ();
|
|
if (child == -1) {
|
|
/* error */
|
|
} else if (!child) {
|
|
/* children */
|
|
r_sandbox_system (code, 1);
|
|
write (input[1], "", 1);
|
|
close (input[0]);
|
|
close (input[1]);
|
|
close (output[0]);
|
|
close (output[1]);
|
|
exit (0);
|
|
return false;
|
|
} else {
|
|
/* parent */
|
|
char *res, buf[1024];
|
|
/* Close pipe ends not required in the parent */
|
|
close (output[1]);
|
|
close (input[0]);
|
|
r_cons_break_push (NULL, NULL);
|
|
for (;;) {
|
|
if (r_cons_is_breaked ()) {
|
|
break;
|
|
}
|
|
memset (buf, 0, sizeof (buf));
|
|
ret = read (output[0], buf, sizeof (buf)-1);
|
|
if (ret < 1 || !buf[0]) {
|
|
break;
|
|
}
|
|
buf[sizeof (buf) - 1] = 0;
|
|
res = lang->cmd_str ((RCore*)lang->user, buf);
|
|
//eprintf ("%d %s\n", ret, buf);
|
|
if (res) {
|
|
write (input[1], res, strlen (res)+1);
|
|
free (res);
|
|
} else {
|
|
eprintf ("r_lang_pipe: NULL reply for (%s)\n", buf);
|
|
write (input[1], "", 1); // NULL byte
|
|
}
|
|
}
|
|
r_cons_break_pop ();
|
|
/* workaround to avoid stdin closed */
|
|
if (safe_in != -1) {
|
|
close (safe_in);
|
|
}
|
|
safe_in = open (ttyname(0), O_RDONLY);
|
|
if (safe_in != -1) {
|
|
dup2 (safe_in, 0);
|
|
} else {
|
|
eprintf ("Cannot open ttyname(0) %s\n", ttyname(0));
|
|
}
|
|
}
|
|
|
|
close (input[0]);
|
|
close (input[1]);
|
|
close (output[0]);
|
|
close (output[1]);
|
|
if (safe_in != -1) {
|
|
close (safe_in);
|
|
}
|
|
waitpid (child, NULL, 0);
|
|
return true;
|
|
#else
|
|
#if __WINDOWS__
|
|
HANDLE hThread = 0;
|
|
char *r2pipe_var = r_str_newf ("R2PIPE_IN%x", _getpid ());
|
|
char *r2pipe_paz = r_str_newf ("\\\\.\\pipe\\%s", r2pipe_var);
|
|
SetEnvironmentVariable ("R2PIPE_PATH", r2pipe_var);
|
|
hPipeInOut = CreateNamedPipe (r2pipe_paz,
|
|
PIPE_ACCESS_DUPLEX,
|
|
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES,
|
|
PIPE_BUF_SIZE,
|
|
PIPE_BUF_SIZE,
|
|
0, NULL);
|
|
hproc = myCreateChildProcess (code);
|
|
if (hproc) {
|
|
bStopThread = FALSE;
|
|
hThread = CreateThread (NULL, 0, ThreadFunction, lang, 0,0);
|
|
WaitForSingleObject (hproc, INFINITE);
|
|
bStopThread = TRUE;
|
|
DeleteFile (r2pipe_paz);
|
|
WaitForSingleObject (hThread, INFINITE);
|
|
CloseHandle (hPipeInOut);
|
|
}
|
|
free (r2pipe_var);
|
|
free (r2pipe_paz);
|
|
return hproc != NULL;
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
static struct r_lang_plugin_t r_lang_plugin_pipe = {
|
|
.name = "pipe",
|
|
.ext = "pipe",
|
|
.license = "LGPL",
|
|
.desc = "Use #!pipe node script.js",
|
|
.run = lang_pipe_run,
|
|
.run_file = (void*)lang_pipe_file,
|
|
};
|