summaryrefslogtreecommitdiff
path: root/src/debug/ptrace/ptrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/debug/ptrace/ptrace.c')
-rw-r--r--src/debug/ptrace/ptrace.c449
1 files changed, 449 insertions, 0 deletions
diff --git a/src/debug/ptrace/ptrace.c b/src/debug/ptrace/ptrace.c
new file mode 100644
index 0000000..8840ce6
--- /dev/null
+++ b/src/debug/ptrace/ptrace.c
@@ -0,0 +1,449 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * ptrace.c - débogage à l'aide de ptrace()
+ *
+ * Copyright (C) 2008 Cyrille Bagard
+ *
+ * This file is part of OpenIDA.
+ *
+ * OpenIDA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * OpenIDA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "ptrace.h"
+
+
+#include <malloc.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+
+
+#include "options.h"
+#include "../debugger-int.h"
+#include "../../panel/log.h"
+
+
+
+
+/** Partie ptrace() **/
+#include <sys/ptrace.h>
+#include <sys/wait.h>
+//#include <linux/user.h>
+#include <sys/syscall.h> /* For SYS_write etc */
+#include <sys/reg.h>
+/** Partie ptrace() **/
+
+
+
+
+#define _(str) str
+
+
+
+
+/* Débogueur utilisant ptrace() (instance) */
+struct _GPtraceDebugger
+{
+ GBinaryDebugger parent; /* A laisser en premier */
+
+ GCond *cond; /* Poursuite du déroulement */
+ GMutex *mutex; /* Accès à la condition */
+
+ ptrace_options *options; /* Configuration du débogage */
+
+ pid_t child; /* Processus suivi lancé */
+
+ gboolean run_again; /* Reprise du débogage */
+
+};
+
+/* Débogueur utilisant ptrace() (classe) */
+struct _GPtraceDebuggerClass
+{
+ GBinaryDebuggerClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en marche le débogueur utilisant ptrace(). */
+bool g_ptrace_debugger_run(GPtraceDebugger *);
+
+/* Remet en marche le débogueur utilisant ptrace(). */
+bool g_ptrace_debugger_resume(GPtraceDebugger *);
+
+/* Tue le débogueur utilisant ptrace(). */
+bool g_ptrace_debugger_kill(GPtraceDebugger *);
+
+/* Procède à un débogage via ptrace(). */
+void *ptrace_thread(GPtraceDebugger *);
+
+/* Fournit la valeur des registres de l'architecture. */
+register_value *get_register_values_using_ptrace_debugger(GPtraceDebugger *, size_t *);
+
+/* Initialise la classe du débogueur utilisant ptrace(). */
+static void g_ptrace_debugger_class_init(GPtraceDebuggerClass *);
+
+/* Procède à l'initialisation du débogueur utilisant ptrace(). */
+static void g_ptrace_debugger_init(GPtraceDebugger *);
+
+
+
+/* Indique le type définit par la GLib pour le débogueur ptrace(). */
+G_DEFINE_TYPE(GPtraceDebugger, g_ptrace_debugger, G_TYPE_BINARY_DEBUGGER);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe de débogueur à initialiser. *
+* *
+* Description : Initialise la classe du débogueur utilisant ptrace(). *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_ptrace_debugger_class_init(GPtraceDebuggerClass *klass)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : debugger = instance de débogueur à préparer. *
+* *
+* Description : Procède à l'initialisation du débogueur utilisant ptrace(). *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_ptrace_debugger_init(GPtraceDebugger *debugger)
+{
+ GBinaryDebugger *parent; /* Instance parente */
+
+ parent = G_BINARY_DEBUGGER(debugger);
+
+ parent->run = (basic_debugger_fc)g_ptrace_debugger_run;
+ parent->resume = (resume_debugger_fc)g_ptrace_debugger_resume;
+ parent->kill = (basic_debugger_fc)g_ptrace_debugger_kill;
+
+ parent->get_reg_values = (get_register_values_fc)get_register_values_using_ptrace_debugger;
+
+ debugger->cond = g_cond_new();
+ debugger->mutex = g_mutex_new();
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : debugger = débogueur à lancer. *
+* *
+* Description : Met en marche le débogueur utilisant ptrace(). *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_ptrace_debugger_run(GPtraceDebugger *debugger)
+{
+ GError *error; /* Bilan de création de thread */
+
+ if (debugger->options == NULL)
+ debugger->options = create_ptrace_options_from_binary(G_BINARY_DEBUGGER(debugger)->binary);
+
+ if (debugger->options == NULL)
+ return false;
+
+
+
+
+ if (!g_thread_create((GThreadFunc)ptrace_thread, debugger, FALSE, &error))
+ {
+ printf ("Failed to create the thread: %s\n", error->message);
+ }
+
+
+ /*
+ printf("Start Debugger with bin :: %p\n", G_BINARY_DEBUGGER_GET_IFACE(debugger)->binary);
+
+ g_signal_emit_by_name(debugger, "debugger-stopped", (uint64_t)0xdeadbeaf);
+ */
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : debugger = débogueur à relancer. *
+* *
+* Description : Remet en marche le débogueur utilisant ptrace(). *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_ptrace_debugger_resume(GPtraceDebugger *debugger)
+{
+ g_mutex_lock(debugger->mutex);
+ debugger->run_again = TRUE;
+ g_cond_signal(debugger->cond);
+ g_mutex_unlock(debugger->mutex);
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : debugger = débogueur à relancer. *
+* *
+* Description : Tue le débogueur utilisant ptrace(). *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_ptrace_debugger_kill(GPtraceDebugger *debugger)
+{
+ int ret; /* Bilan de l'appel système */
+
+ ret = kill(debugger->child, SIGKILL);
+ if (ret != 0) perror("kill");
+
+ debugger->child = 0;
+
+ g_mutex_lock(debugger->mutex);
+ debugger->run_again = TRUE;
+ g_cond_signal(debugger->cond);
+ g_mutex_unlock(debugger->mutex);
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : debugger = encadrement associée à l'opération. *
+* *
+* Description : Procède à un débogage via ptrace(). *
+* *
+* Retour : ??? *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void *ptrace_thread(GPtraceDebugger *debugger)
+{
+
+
+
+ long last_eip; /* Ancien point d'arrêt */
+ long cur_eip; /* Point d'arrêt courant */
+
+
+ long orig_eax;
+ int status;
+
+
+ pid_t pid;
+
+
+ bool first_run; /* Premier passage ? */
+
+
+ debugger->child = fork();
+
+ switch (debugger->child)
+ {
+ case -1:
+ perror("fork");
+ exit(-1);
+ break;
+
+ case 0:
+ ptrace(PTRACE_TRACEME, 0, NULL, NULL);
+ run_ptrace_options_process(debugger->options);
+ _exit(-1);
+ break;
+
+ default:
+
+ gdk_threads_enter();
+
+ log_variadic_message(LMT_PROCESS, _("Starting to debug %s..."),
+ openida_binary_get_filename(G_BINARY_DEBUGGER(debugger)->binary));
+
+ gdk_flush ();
+ gdk_threads_leave();
+
+ first_run = true;
+
+ while(1)
+ {
+
+
+
+
+ pid = waitpid(debugger->child, &status, 0/*WNOHANG*/);
+ //wait(&status);
+
+ printf("Status :: %d\n", WIFEXITED(status));
+
+ if(WIFEXITED(status))
+ break;
+
+ orig_eax = ptrace(PTRACE_PEEKUSER,
+ debugger->child, 4 * ORIG_EAX, NULL);
+ if (orig_eax == -1)
+ {
+ //printf("errno :: %d vs %d\n", errno, ESRCH);
+ perror("ptrace()");
+ }
+
+ /* get GTK thread lock */
+ gdk_threads_enter();
+
+
+ //gtk_text_buffer_insert_at_cursor (info->buffer, "Thread waiting for resume...\n", -1);
+
+ //gdk_flush ();
+
+ /* release GTK thread lock */
+ //gdk_threads_leave();
+
+
+ /* Notification du point d'arrêt */
+
+ cur_eip = ptrace(PTRACE_PEEKUSER, debugger->child, 4 * EIP, NULL);
+
+ if (first_run)
+ {
+ last_eip = cur_eip;
+ first_run = false;
+ }
+
+ g_signal_emit_by_name(debugger, "debugger-stopped",
+ (uint64_t)last_eip, (uint64_t)cur_eip);
+
+ last_eip = cur_eip;
+
+ /* release GTK thread lock */
+ gdk_flush ();
+
+ gdk_threads_leave();
+
+ g_mutex_lock(debugger->mutex);
+ while (!debugger->run_again)
+ g_cond_wait(debugger->cond, debugger->mutex);
+ debugger->run_again = FALSE;
+ g_mutex_unlock(debugger->mutex);
+
+
+ if (debugger->child == 0) break;
+
+
+ ptrace(PTRACE_SYSCALL, debugger->child, NULL, NULL);
+
+ }
+
+ log_variadic_message(LMT_PROCESS, _("Finished to debug %s..."),
+ openida_binary_get_filename(G_BINARY_DEBUGGER(debugger)->binary));
+
+ break;
+
+ }
+
+ return NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : debugger = débogueur à utiliser. *
+* count = nombre de transmissions effetuées. *
+* *
+* Description : Fournit la valeur des registres de l'architecture. *
+* *
+* Retour : Tableau de valeurs transmises à libérer de la mémoire / NULL.*
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+register_value *get_register_values_using_ptrace_debugger(GPtraceDebugger *debugger, size_t *count)
+{
+ register_value *result; /* Liste de valeurs renvoyées */
+ long ret; /* Valeur de registre */
+
+ *count = 9;
+ result = (register_value *)calloc(*count, sizeof(register_value));
+
+ ret = ptrace(PTRACE_PEEKUSER, debugger->child, 4 * EAX, NULL);
+ result[0].name = "eax";
+ result[0].value = ret;
+
+ ret = ptrace(PTRACE_PEEKUSER, debugger->child, 4 * EBX, NULL);
+ result[1].name = "ebx";
+ result[1].value = ret;
+
+ ret = ptrace(PTRACE_PEEKUSER, debugger->child, 4 * ECX, NULL);
+ result[2].name = "ecx";
+ result[2].value = ret;
+
+ ret = ptrace(PTRACE_PEEKUSER, debugger->child, 4 * EDX, NULL);
+ result[3].name = "edx";
+ result[3].value = ret;
+
+ ret = ptrace(PTRACE_PEEKUSER, debugger->child, 4 * ESI, NULL);
+ result[4].name = "esi";
+ result[4].value = ret;
+
+ ret = ptrace(PTRACE_PEEKUSER, debugger->child, 4 * EDI, NULL);
+ result[5].name = "edi";
+ result[5].value = ret;
+
+ ret = ptrace(PTRACE_PEEKUSER, debugger->child, 4 * EBP, NULL);
+ result[6].name = "ebp";
+ result[6].value = ret;
+
+ ret = ptrace(PTRACE_PEEKUSER, debugger->child, 4 * UESP, NULL);
+ result[7].name = "esp";
+ result[7].value = ret;
+
+ ret = ptrace(PTRACE_PEEKUSER, debugger->child, 4 * EIP, NULL);
+ result[8].name = "eip";
+ result[8].value = ret;
+
+ return result;
+
+}