Skip to content

Commit 78d4aee

Browse files
author
collin
committed
initial release on github
1 parent 4bb618e commit 78d4aee

File tree

13 files changed

+2003
-0
lines changed

13 files changed

+2003
-0
lines changed

hijack/hijack.c

Lines changed: 880 additions & 0 deletions
Large diffs are not rendered by default.

hijack/jni/Android.mk

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Copyright (C) 2009 The Android Open Source Project
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
#
15+
LOCAL_PATH := $(call my-dir)
16+
17+
include $(CLEAR_VARS)
18+
19+
LOCAL_MODULE := hijack
20+
LOCAL_SRC_FILES := ../hijack.c
21+
LOCAL_ARM_MODE := arm
22+
LOCAL_CFLAGS := -g
23+
24+
include $(BUILD_EXECUTABLE)

instruments/base/base.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Collin's Binary Instrumentation Tool/Framework for Android
3+
* Collin Mulliner <collin[at]mulliner.org>
4+
* http://www.mulliner.org/android/
5+
*
6+
* (c) 2012,2013
7+
*
8+
* License: LGPL v2.1
9+
*
10+
*/
11+
12+
#define _GNU_SOURCE
13+
#include <stdio.h>
14+
#include <sys/types.h>
15+
#include <sys/stat.h>
16+
#include <fcntl.h>
17+
#include <dlfcn.h>
18+
#include <sys/socket.h>
19+
#include <netinet/in.h>
20+
#include <sys/select.h>
21+
#include <string.h>
22+
#include <termios.h>
23+
#include <pthread.h>
24+
#include <sys/epoll.h>
25+
26+
#include <jni.h>
27+
28+
#include "util.h"
29+
#include "hook.h"
30+
31+
32+
//static void __attribute__ ((constructor)) base_my_init(void);
33+
34+
static char logfile[] = "/data/local/tmp/adbi.log";
35+
36+
static void logmsgtofile(char *msg)
37+
{
38+
int fp = open(logfile, O_WRONLY|O_APPEND);
39+
write(fp, msg, strlen(msg));
40+
close(fp);
41+
}
42+
43+
static void logmsgtostdout(char *msg)
44+
{
45+
write(1, msg, strlen(msg));
46+
}
47+
48+
void* set_logfunction(void *func)
49+
{
50+
void *old = log_function;
51+
log_function = func;
52+
return old;
53+
}
54+
55+
static void base_my_init(void)
56+
{
57+
// set the log_function
58+
log_function = logmsgtofile;
59+
}

instruments/base/base.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*
2+
* Collin's Binary Instrumentation Tool/Framework for Android
3+
* Collin Mulliner <collin[at]mulliner.org>
4+
* http://www.mulliner.org/android/
5+
*
6+
* (c) 2012,2013
7+
*
8+
* License: LGPL v2.1
9+
*
10+
*/
11+
12+
void* set_logfunction(void *func);

instruments/base/hook.c

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
/*
2+
* Collin's Binary Instrumentation Tool/Framework for Android
3+
* Collin Mulliner <collin[at]mulliner.org>
4+
* http://www.mulliner.org/android/
5+
*
6+
* (c) 2012,2013
7+
*
8+
* License: LGPL v2.1
9+
*
10+
*/
11+
#define _GNU_SOURCE
12+
#include <stdio.h>
13+
#include <sys/types.h>
14+
#include <sys/stat.h>
15+
#include <fcntl.h>
16+
#include <dlfcn.h>
17+
#include <sys/socket.h>
18+
#include <netinet/in.h>
19+
#include <sys/select.h>
20+
#include <string.h>
21+
#include <termios.h>
22+
#include <pthread.h>
23+
#include <sys/epoll.h>
24+
25+
#include <jni.h>
26+
27+
#include "util.h"
28+
#include "hook.h"
29+
30+
//void __attribute__ ((constructor)) my_init(void);
31+
32+
void inline hook_cacheflush(unsigned int begin, unsigned int end)
33+
{
34+
const int syscall = 0xf0002;
35+
__asm __volatile (
36+
"mov r0, %0\n"
37+
"mov r1, %1\n"
38+
"mov r7, %2\n"
39+
"mov r2, #0x0\n"
40+
"svc 0x00000000\n"
41+
:
42+
: "r" (begin), "r" (end), "r" (syscall)
43+
: "r0", "r1", "r7"
44+
);
45+
}
46+
47+
int hook_direct(struct hook_t *h, unsigned int addr, void *hookf)
48+
{
49+
int i;
50+
51+
log("addr = %x\n", addr)
52+
log("hookf = %x\n", hookf)
53+
54+
if ((addr % 4 == 0 && (unsigned int)hookf % 4 != 0) || (addr % 4 != 0 && (unsigned int)hookf % 4 == 0))
55+
log("addr 0x%x and hook 0x%x\n don't match!\n", addr, hookf)
56+
57+
//log("ARM\n")
58+
h->thumb = 0;
59+
h->patch = (unsigned int)hookf;
60+
h->orig = addr;
61+
log("orig = %x\n", h->orig)
62+
h->jump[0] = 0xe59ff000; // LDR pc, [pc, #0]
63+
h->jump[1] = h->patch;
64+
h->jump[2] = h->patch;
65+
for (i = 0; i < 3; i++)
66+
h->store[i] = ((int*)h->orig)[i];
67+
for (i = 0; i < 3; i++)
68+
((int*)h->orig)[i] = h->jump[i];
69+
70+
hook_cacheflush((unsigned int)h->orig, (unsigned int)h->orig+sizeof(h->jumpt));
71+
return 1;
72+
}
73+
74+
int hook(struct hook_t *h, int pid, char *libname, char *funcname, void *hook_arm, void *hook_thumb)
75+
{
76+
unsigned long int addr;
77+
int i;
78+
79+
if (find_name(pid, funcname, libname, &addr) < 0) {
80+
log("can't find: %s\n", funcname)
81+
return 0;
82+
}
83+
84+
log("hooking: %s = 0x%x ", funcname, addr)
85+
strncpy(h->name, funcname, sizeof(h->name)-1);
86+
87+
if (addr % 4 == 0) {
88+
log("ARM using 0x%x\n", hook_arm)
89+
h->thumb = 0;
90+
h->patch = (unsigned int)hook_arm;
91+
h->orig = addr;
92+
h->jump[0] = 0xe59ff000; // LDR pc, [pc, #0]
93+
h->jump[1] = h->patch;
94+
h->jump[2] = h->patch;
95+
for (i = 0; i < 3; i++)
96+
h->store[i] = ((int*)h->orig)[i];
97+
for (i = 0; i < 3; i++)
98+
((int*)h->orig)[i] = h->jump[i];
99+
}
100+
else {
101+
if ((unsigned long int)hook_thumb % 4 == 0)
102+
log("warning hook is not thumb 0x%x\n", hook_thumb)
103+
h->thumb = 1;
104+
log("THUMB using 0x%x\n", hook_thumb)
105+
h->patch = (unsigned int)hook_thumb;
106+
h->orig = addr;
107+
h->jumpt[1] = 0xb4;
108+
h->jumpt[0] = 0x30; // push {r4,r5}
109+
h->jumpt[3] = 0xa5;
110+
h->jumpt[2] = 0x03; // add r5, pc, #12
111+
h->jumpt[5] = 0x68;
112+
h->jumpt[4] = 0x2d; // ldr r5, [r5]
113+
h->jumpt[7] = 0xb0;
114+
h->jumpt[6] = 0x02; // add sp,sp,#8
115+
h->jumpt[9] = 0xb4;
116+
h->jumpt[8] = 0x20; // push {r5}
117+
h->jumpt[11] = 0xb0;
118+
h->jumpt[10] = 0x81; // sub sp,sp,#4
119+
h->jumpt[13] = 0xbd;
120+
h->jumpt[12] = 0x20; // pop {r5, pc}
121+
h->jumpt[15] = 0x46;
122+
h->jumpt[14] = 0xaf; // mov pc, r5 ; just to pad to 4 byte boundary
123+
memcpy(&h->jumpt[16], (unsigned char*)&h->patch, sizeof(unsigned int));
124+
unsigned int orig = addr - 1; // sub 1 to get real address
125+
for (i = 0; i < 20; i++) {
126+
h->storet[i] = ((unsigned char*)orig)[i];
127+
//log("%0.2x ", h->storet[i])
128+
}
129+
//log("\n")
130+
for (i = 0; i < 20; i++) {
131+
((unsigned char*)orig)[i] = h->jumpt[i];
132+
//log("%0.2x ", ((unsigned char*)orig)[i])
133+
}
134+
}
135+
hook_cacheflush((unsigned int)h->orig, (unsigned int)h->orig+sizeof(h->jumpt));
136+
return 1;
137+
}
138+
139+
void hook_precall(struct hook_t *h)
140+
{
141+
int i;
142+
143+
if (h->thumb) {
144+
unsigned int orig = h->orig - 1;
145+
for (i = 0; i < 20; i++) {
146+
((unsigned char*)orig)[i] = h->storet[i];
147+
}
148+
}
149+
else {
150+
for (i = 0; i < 3; i++)
151+
((int*)h->orig)[i] = h->store[i];
152+
}
153+
hook_cacheflush((unsigned int)h->orig, (unsigned int)h->orig+sizeof(h->jumpt));
154+
}
155+
156+
void hook_postcall(struct hook_t *h)
157+
{
158+
int i;
159+
160+
if (h->thumb) {
161+
unsigned int orig = h->orig - 1;
162+
for (i = 0; i < 20; i++)
163+
((unsigned char*)orig)[i] = h->jumpt[i];
164+
}
165+
else {
166+
for (i = 0; i < 3; i++)
167+
((int*)h->orig)[i] = h->jump[i];
168+
}
169+
hook_cacheflush((unsigned int)h->orig, (unsigned int)h->orig+sizeof(h->jumpt));
170+
}
171+
172+
void unhook(struct hook_t *h)
173+
{
174+
log("unhooking %s = %x hook = %x ", h->name, h->orig, h->patch)
175+
hook_precall(h);
176+
}
177+
178+
/*
179+
* workaround for blocked socket API when process does not have network
180+
* permissions
181+
*
182+
* this code simply opens a pseudo terminal (pty) which gives us a
183+
* file descriptor. the pty then can be used by another process to
184+
* communicate with our instrumentation code. an example program
185+
* would be a simple socket-to-pty-bridge
186+
*
187+
* this function just creates and configures the pty
188+
* communication (read, write, poll/select) has to be implemented by hand
189+
*
190+
*/
191+
int start_coms(int *coms, char *ptsn)
192+
{
193+
if (!coms) {
194+
log("coms == null!\n")
195+
return 0;
196+
}
197+
198+
*coms = open("/dev/ptmx", O_RDWR|O_NOCTTY);
199+
if (*coms <= 0) {
200+
log("posix_openpt failed\n")
201+
return 0;
202+
}
203+
//else
204+
// log("pty created\n")
205+
if (unlockpt(*coms) < 0) {
206+
log("unlockpt failed\n")
207+
return 0;
208+
}
209+
210+
if (ptsn)
211+
strcpy(ptsn, (char*)ptsname(*coms));
212+
213+
struct termios ios;
214+
tcgetattr(*coms, &ios);
215+
ios.c_lflag = 0; // disable ECHO, ICANON, etc...
216+
tcsetattr(*coms, TCSANOW, &ios);
217+
218+
return 1;
219+
}

instruments/base/hook.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Collin's Binary Instrumentation Tool/Framework for Android
3+
* Collin Mulliner <collin[at]mulliner.org>
4+
*
5+
* (c) 2012,2013
6+
*
7+
* License: LGPL v2.1
8+
*
9+
*/
10+
11+
void (*log_function)(char *logmsg);
12+
13+
#define log(...) \
14+
{char __msg[1024] = {0};\
15+
snprintf(__msg, sizeof(__msg)-1, __VA_ARGS__);\
16+
log_function(__msg); }
17+
18+
struct hook_t {
19+
unsigned int jump[3];
20+
unsigned int store[3];
21+
unsigned char jumpt[20];
22+
unsigned char storet[20];
23+
unsigned int orig;
24+
unsigned int patch;
25+
unsigned char thumb;
26+
unsigned char name[128];
27+
void *data;
28+
};
29+
30+
int start_coms(int *coms, char *ptsn);
31+
32+
void hook_cacheflush(unsigned int begin, unsigned int end);
33+
void hook_precall(struct hook_t *h);
34+
void hook_postcall(struct hook_t *h);
35+
int hook(struct hook_t *h, int pid, char *libname, char *funcname, void *hook_arm, void *hook_thumb);
36+
void unhook(struct hook_t *h);

instruments/base/jni/Android.mk

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Copyright (C) 2009 The Android Open Source Project
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
#
15+
LOCAL_PATH := $(call my-dir)
16+
17+
include $(CLEAR_VARS)
18+
19+
LOCAL_MODULE := base
20+
LOCAL_SRC_FILES := ../util.c ../hook.c ../base.c
21+
LOCAL_ARM_MODE := arm
22+
23+
include $(BUILD_STATIC_LIBRARY)

instruments/base/jni/Application.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
APP_MODULES := base

0 commit comments

Comments
 (0)