質問するログイン新規登録

質問編集履歴

2

追記しました

2019/08/22 18:01

投稿

退会済みユーザー
title CHANGED
File without changes
body CHANGED
@@ -21,4 +21,123 @@
21
21
  Continuing.
22
22
 
23
23
  //これ以降何も表示されない。sampleの方は動き続けている
24
+ ```
25
+
26
+ ###追記
27
+ やはりaddrの値が違ったようで、自分で書いたコードでPTRACE_GETREGSでEIPを取得し、その位置にint3を書き込むことでブレークポイントを仕掛けることには成功しました。ただ、上記のサイトのように、目的の関数にブレークポイントを仕掛けることは未だできていません。目的の関数にブレークポイントを仕掛けるにはどうしたらいいでしょうか。
28
+
29
+ また、addrの値が違うなら、そもそもnmコマンドで表示されているアドレスは一体何なのでしょうか。
30
+ [あなたが知らないプログラムの真の始まり――main()関数の前にあるスタートアップとは (2/3)](https://www.atmarkit.co.jp/ait/articles/1703/01/news173_2.html)
31
+ こちらの記事によると、nmやreadelfで表示できるアドレスは実際に実行される際のアドレスのようですが、私の環境ではどうにも一致していません。
32
+
33
+ 以下自分で書いたコードです。都合上32bitでコンパイルしています。
34
+
35
+ ```
36
+ gcc -m32 -o TestHook TestHook.c
37
+ ```
38
+
39
+ ```TestHook
40
+ #include <stdio.h>
41
+ #include <stdlib.h>
42
+ #include <sys/ptrace.h>
43
+ #include <unistd.h>
44
+ #include <sys/types.h>
45
+ #include <sys/wait.h>
46
+ #include <sys/user.h>
47
+ #include <elf.h>
48
+
49
+
50
+ //forkしたプロセスをexecvp()で別のプロセスに置き換える
51
+ int child(int argc, char* argv[])
52
+ {
53
+ if(argc < 2){
54
+ puts("error : argument");
55
+ return -1;
56
+ }
57
+
58
+ long ret;
59
+ ret = ptrace(PTRACE_TRACEME, 0, 0, 0);
60
+ if(ret < 0){
61
+ perror("failed PTRACE_TRACEME");
62
+ exit(1);
63
+ }
64
+
65
+ ret = execvp(argv[1], argv);
66
+ if(ret < 0){
67
+ perror("failed to execvp");
68
+ exit(1);
69
+ }
70
+ puts("error"); //通常ならば実行されない
71
+ return 0;
72
+ }
73
+
74
+ //子の状態変化を待ち、SIGTRAPを受け取ると再開.int3を入れたりいろいろやる
75
+ void parent(pid_t pid)
76
+ {
77
+  int status;
78
+ int ret;
79
+ struct user_regs_struct regs;
80
+ unsigned addr;
81
+ unsigned original_data;
82
+ unsigned trap_data;
83
+ unsigned readback_data;
84
+ addr = strtol("0x0000051d", NULL, 0);
85
+
86
+ waitpid(pid, &status, 0);
87
+ if(WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP){
88
+
89
+ //レジスタの値を取得
90
+ ret = ptrace(PTRACE_GETREGS, pid, 0, &regs);
91
+ if(ret < 0){
92
+ puts("Failed PTRACE_GETREGS");
93
+ }
94
+ printf("Child started. EIP = 0x%08x\n", regs.eip);
95
+
96
+ //元データの読み出し
97
+ original_data = ptrace(PTRACE_PEEKTEXT, pid, (void *)regs.eip, 0);
98
+ if(original_data == -1){
99
+ puts("PEEK_TEXT error");
100
+ }
101
+ printf("Original data at 0x%08x : 0x%08x\n",regs.eip, original_data);
102
+
103
+ //int3の書き込み
104
+ trap_data = (original_data & 0xFFFFFF00) | 0xCC;
105
+ ret = ptrace(PTRACE_POKETEXT, pid, (void *)regs.eip, (void *)trap_data);
106
+ if(ret < 0){
107
+ puts("Failed to PTRACE_POKETEXT");
108
+ }
109
+
110
+ //書き込み後のデータの所得
111
+ readback_data = ptrace(PTRACE_PEEKTEXT, pid, (void *)regs.eip, 0);
112
+ printf("After trap, data at 0x%08x : 0x%08x\n",regs.eip, readback_data);
113
+
114
+ sleep(3);
115
+
116
+ puts("\nRestart child process.");
117
+ puts("----------------------------");
118
+ ptrace(PTRACE_CONT, pid, 0, 0); //停止している子プロセスの再開
119
+ waitpid(pid, &status, 0);
120
+ if(WIFSTOPPED(status)){
121
+ puts("Breakpoint int3");
122
+ }
123
+ }
124
+ }
125
+
126
+
127
+ int main(int argc, char *argv[])
128
+ {
129
+ pid_t child_pid = fork();
130
+
131
+ switch(child_pid){
132
+ case 0:
133
+ {
134
+ child(argc, argv);
135
+ }
136
+ default :
137
+ {
138
+ parent(child_pid);
139
+ }
140
+ }
141
+ }
142
+
24
143
  ```

1

リンクを修正しました

2019/08/22 18:01

投稿

退会済みユーザー
title CHANGED
File without changes
body CHANGED
@@ -1,11 +1,11 @@
1
1
  現在、ptraceを使ったデバッグの勉強をしています。以下のサイトのデバッガを試してみたのですが上手くいきません。元のコードに手は加えていません。
2
- https://th0x4c.github.io/blog/2013/08/27/debug-debugging-with-ptrace/
2
+ [[Debug] Ptrace によるデバッグ]( https://th0x4c.github.io/blog/2013/08/27/debug-debugging-with-ptrace/)
3
3
 
4
4
  調べてみると、アタッチはできているので、どうやら関数p_break()内のPTRACE_PEEKTEXTでデータを読み取る際に失敗しているようです。
5
5
  恐らくaddrの値が問題だと考えているのですが、一向に解決しません。どうしたら正しく動作するでしょうか?
6
6
 
7
7
 
8
- 以下は実際に試した様子です。ubuntuの64bitを使用しています。
8
+ 以下は実際に試した様子です。vmware上ubuntu-64bitを使用しています。
9
9
 
10
10
  ```
11
11
  $ nm sample | grep func
@@ -20,5 +20,5 @@
20
20
  Breakpoint at 0x68a.
21
21
  Continuing.
22
22
 
23
- これ以降何も表示されない。sampleの方は動き続けている
23
+ //これ以降何も表示されない。sampleの方は動き続けている
24
24
  ```