moonlight flow

android LD_PRELOAD实现API HOOK - moonflow - 推酷
android LD_PRELOAD实现API HOOK - moonflow
使用LD_PRELOAD来实现API HOOK,各种android下HOOK技术学习
一、代码编译
hook.c(截取自pof的ldpreloadhook,a quick open/close/ioctl/read/write/free symbol hooker)
#include &stdarg.h&
#include &stdlib.h&
#include &string.h&
#include &fcntl.h&
#include &stdio.h&
#include &dlfcn.h&
#include &sys/types.h&
#include &sys/stat.h&
#include &stdlib.h&
#include &signal.h&
#define DPRINTF(format, args...)
fprintf(stderr, format, ## args)
#ifndef RTLD_NEXT
#define RTLD_NEXT ((void *) -1l)
#define REAL_LIBC RTLD_NEXT
typedef int request_t;
typedef void (*sighandler_t)(int);
static int data_w_fd = -1, hook_fd = -1, data_r_fd = -1;
static const char *data_w_file = &/data/local/tmp/write_data.bin&;
static const char *data_r_file = &/data/local/tmp/read_data.bin&;
static void _libhook_init() __attribute__ ((constructor));
static void _libhook_init() {
/* causes segfault on some android, uncomment if you need it */
//unsetenv(&LD_PRELOAD&);
printf(&[] Hooking!\n&);
ssize_t write (int fd, const void *buf, size_t count);
void free (void *buf);
int open (const char *pathname, int flags, ...){
static int (*func_open) (const char *, int, mode_t) = NULL;
setenv(&SPYFILE&, &spyfile&, 0);
char *spy_file = getenv(&SPYFILE&);
if (!func_open)
func_open = (int (*) (const char *, int, mode_t)) dlsym (REAL_LIBC, &open&);
va_start (args, flags);
mode = va_arg (args, int);
va_end (args);
if (strcmp (pathname, spy_file)){
fd = func_open (pathname, flags, mode);
DPRINTF (&HOOK: opened file %s (fd=%d)\n&, pathname, fd);
data_w_fd = func_open (data_w_file, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
data_r_fd = func_open (data_r_file, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
hook_fd = func_open (pathname, flags, mode);
/* write the delimiter each time we open the files */
if (getenv(&DELIMITER&) != NULL) {
write (data_r_fd, getenv(&DELIMITER&), strlen(getenv(&DELIMITER&)));
write (data_w_fd, getenv(&DELIMITER&), strlen(getenv(&DELIMITER&)));
DPRINTF (&HOOK: opened hooked file %s (fd=%d)\n&, pathname, hook_fd);
return hook_
int strcmp(const char *s1, const char *s2) {
static int (*func_strcmp) (const char *, const char *) = NULL;
int retval = 0;
if (! func_strcmp)
func_strcmp = (int (*) (const char*, const char*)) dlsym (REAL_LIBC, &strcmp&);
if (getenv(&SPYSTR&) != NULL) {
DPRINTF (&HOOK: strcmp( \&%s\& , \&%s\& )\n&, s1, s2);
retval = func_strcmp (s1, s2);
int strncmp(const char *s1, const char *s2, size_t n) {
static int (*func_strncmp) (const char *, const char *, size_t) = NULL;
int retval = 0;
if (! func_strncmp)
func_strncmp = (int (*) (const char*, const char*, size_t)) dlsym (REAL_LIBC, &strncmp&);
if (getenv(&SPYSTR&) != NULL) {
DPRINTF (&HOOK: strncmp( \&%s\& , \&%s\& , %zd )\n&, s1, s2, n);
retval = func_strncmp (s1, s2, n);
int close (int fd){
static int (*func_close) (int) = NULL;
int retval = 0;
setenv(&SPYFILE&, &spyfile&, 0);
char *spy_file = getenv(&SPYFILE&);
if (! func_close)
func_close = (int (*) (int)) dlsym (REAL_LIBC, &close&);
if (fd == hook_fd)
DPRINTF (&HOOK: closed hooked file %s (fd=%d)\n&, spy_file, fd);
DPRINTF (&HOOK: closed file descriptor (fd=%d)\n&, fd);
retval = func_close (fd);
int ioctl (int fd, request_t request, ...){
static int (*func_ioctl) (int, request_t, void *) = NULL;
setenv(&SPYFILE&, &spyfile&, 0);
char *spy_file = getenv(&SPYFILE&);
if (! func_ioctl)
func_ioctl = (int (*) (int, request_t, void *)) dlsym (REAL_LIBC, &ioctl&);
va_start (args, request);
argp = va_arg (args, void *);
va_end (args);
if (fd != hook_fd) {
DPRINTF (&HOOK: ioctl (fd=%d)\n&, fd);
return func_ioctl (fd, request, argp);
DPRINTF (&HOOK: ioctl on hooked file %s (fd=%d)\n&, spy_file, fd);
/* Capture the ioctl() calls */
return func_ioctl (hook_fd, request, argp);
ssize_t read (int fd, void *buf, size_t count){
static ssize_t (*func_read) (int, const void*, size_t) = NULL;
static ssize_t (*func_write) (int, const void*, size_t) = NULL;
ssize_t retval = 0;
setenv(&SPYFILE&, &spyfile&, 0);
char *spy_file = getenv(&SPYFILE&);
if (! func_read)
func_read = (ssize_t (*) (int, const void*, size_t)) dlsym (REAL_LIBC, &read&);
if (! func_write)
func_write = (ssize_t (*) (int, const void*, size_t)) dlsym (REAL_LIBC, &write&);
if (fd != hook_fd) {
DPRINTF (&HOOK: read %zd bytes from file descriptor (fd=%d)\n&, count, fd);
return func_read (fd, buf, count);
DPRINTF (&HOOK: read %zd bytes from hooked file %s (fd=%d)\n&, count, spy_file, fd);
retval = func_read(fd, buf, count);
char *buf2 = calloc(retval, sizeof(char));
memcpy(buf2, buf, retval);
func_write (data_r_fd, buf2, retval);
free(buf2);
ssize_t write (int fd, const void *buf, size_t count){
static ssize_t (*func_write) (int, const void*, size_t) = NULL;
ssize_t retval = 0;
setenv(&SPYFILE&, &spyfile&, 0);
char *spy_file = getenv(&SPYFILE&);
if (! func_write)
func_write = (ssize_t (*) (int, const void*, size_t)) dlsym (REAL_LIBC, &write&);
if (fd != hook_fd) {
DPRINTF (&HOOK: write %zd bytes to file descriptor (fd=%d)\n&, count, fd);
return func_write (fd, buf, count);
DPRINTF (&HOOK: write %zd bytes to hooked file %s (fd=%d)\n&, count, spy_file, fd);
func_write (hook_fd, buf, count);
retval = func_write (data_w_fd, buf, count);
void free (void *ptr){
static void (*func_free) (void*) = NULL;
char *tmp =
char tmp_buf[1025] = {0};
size_t total = 0;
if (! func_free)
func_free = (void (*) (void*)) dlsym (REAL_LIBC, &free&);
if (getenv(&SPYFREE&) != NULL) {
if (ptr != NULL) {
while (*tmp != '\0') {
tmp_buf[total] = *
if (total == 1024)
if (strlen(tmp_buf) != 0)
DPRINTF(&HOOK: free( ptr[%zd]=%s )\n&,strlen(tmp_buf), tmp_buf);
func_free (ptr);
void *memcpy(void *dest, const void *src, size_t n) {
static void (*func_memcpy) (void*, const void *, size_t) = NULL;
if (! func_memcpy)
func_memcpy = (void (*) (void*, const void *, size_t)) dlsym (REAL_LIBC, &memcpy&);
DPRINTF(&HOOK: memcpy( dest=%p , src=%p, size=%zd )\n&, dest, src, n);
func_memcpy(dest,src,n);
char *tmp =
char tmp_buf[1025] = {0};
size_t total = 0;
DPRINTF(& memcpy buffer: &);
while (total & n) {
tmp_buf[total] = *
DPRINTF(&%02X &, tmp_buf[total]);
if (total == 1024)
DPRINTF(&\n&);
DPRINTF(& memcpy str: [%zd]=%s )\n&,strlen(tmp_buf), tmp_buf);
int puts(const char *s) {
static int (*func_puts) (const char *) = NULL;
int retval = 0;
if (! func_puts)
func_puts = (int (*) (const char*)) dlsym (REAL_LIBC, &puts&);
DPRINTF (&HOOK: puts( \&%s\& )\n&, s);
retval = func_puts (s);
uid_t getuid(void) {
static uid_t (*func_getuid) (void) = NULL;
if (!func_getuid)
func_getuid = (uid_t (*) (void)) dlsym (REAL_LIBC, &getuid&);
uid_t retval = func_getuid();
DPRINTF(&HOOK: getuid returned %d\n&, retval);
int system(const char *command) {
static int (*func_system) (const char *) = NULL;
int retval = 0;
if (! func_system)
func_system = (int (*) (const char*)) dlsym (REAL_LIBC, &system&);
retval = func_system (command);
DPRINTF (&HOOK: system( \&%s\& ) returned %d\n&, command, retval);
void *malloc(size_t size) {
static void (*func_malloc) (size_t) = NULL;
if (! func_malloc)
func_malloc = (void (*) (size_t)) dlsym (REAL_LIBC, &malloc&);
DPRINTF(&HOOK: malloc( size=%zd )\n&, size);
func_malloc(size);
void abort(void) {
static void (*func_abort) (void) = NULL;
if (! func_abort)
func_abort = (void (*) (void)) dlsym (REAL_LIBC, &abort&);
DPRINTF(&HOOK: abort()\n&);
func_abort();
int chmod(const char *path, mode_t mode) {
static int (*func_chmod) (const char *, mode_t) = NULL;
int retval = 0;
if (! func_chmod)
func_chmod = (int (*) (const char*, mode_t)) dlsym (REAL_LIBC, &chmod&);
retval = func_chmod (path, mode);
DPRINTF (&HOOK: chmod( \&%s\&, mode=%o ) returned %d\n&, path, mode, retval);
sighandler_t bsd_signal(int signum, sighandler_t handler) {
static sighandler_t (*func_bsd_signal) (int, sighandler_t) = NULL;
if (! func_bsd_signal)
func_bsd_signal = (sighandler_t (*) (int, sighandler_t)) dlsym (REAL_LIBC, &bsd_signal&);
sighandler_t retval = func_bsd_signal (signum, handler);
DPRINTF (&HOOK: bsd_signal \&%d\& \n&, signum);
int unlink(const char *pathname) {
static int (*func_unlink) (const char *) = NULL;
int retval = 0;
if (! func_unlink)
func_unlink = (int (*) (const char*)) dlsym (REAL_LIBC, &unlink&);
retval = func_unlink (pathname);
DPRINTF (&HOOK: unlink( \&%s\& ) returned %d\n&, pathname, retval);
pid_t fork(void) {
static pid_t (*func_fork) (void) = NULL;
if (!func_fork)
func_fork = (pid_t (*) (void)) dlsym (REAL_LIBC, &fork&);
pid_t retval = func_fork();
DPRINTF(&HOOK: fork() returned %d\n&, retval);
void srand48(long int seedval) {
static void (*func_srand48) (long int) = NULL;
if (! func_srand48)
func_srand48 = (void (*) (long int)) dlsym (REAL_LIBC, &srand48&);
DPRINTF(&HOOK: srand48( size=%ld )\n&, seedval);
func_srand48(seedval);
void *memset(void *s, int c, size_t n) {
static void (*func_memset) (void*, int, size_t) = NULL;
if (! func_memset)
func_memset = (void (*) (void*, int, size_t)) dlsym (REAL_LIBC, &memset&);
DPRINTF(&HOOK: memset( s=%p , c=%d, n=%zd )\n&, s, c, n);
func_memset(s,c,n);
time_t time(time_t *t) {
static time_t (*func_time) (time_t *) = NULL;
time_t retval = 0;
if (! func_time)
func_time = (time_t (*) (time_t *)) dlsym (REAL_LIBC, &time&);
DPRINTF (&HOOK: time( \&%d\& )\n&, t);
retval = func_time (t);
long int lrand48(void) {
static long int (*func_lrand48) (void) = NULL;
if (! func_lrand48)
func_lrand48 = (long int (*) (void)) dlsym (REAL_LIBC, &lrand48&);
long int retval = func_lrand48();
DPRINTF(&HOOK: lrand48() returned %ld\n&, retval);
size_t strlen(const char *s) {
static size_t (*func_strlen) (const char *) = NULL;
int retval = 0;
if (! func_strlen)
func_strlen = (size_t (*) (const char*)) dlsym (REAL_LIBC, &strlen&);
retval = func_strlen (s);
DPRINTF (&HOOK: strlen( \&%s\& ) returned %d\n&, s, retval);
int raise(int sig) {
static int (*func_raise) (int) = NULL;
int retval = 0;
if (! func_raise)
func_raise = (int (*) (int)) dlsym (REAL_LIBC, &raise&);
retval = func_raise (sig);
DPRINTF (&HOOK: raise( \&%d\& ) returned %d\n&, sig, retval);
Android.mk
LOCAL_PATH := $(call my-dir)
# module hook
include $(CLEAR_VARS)
LOCAL_MODULE := hook
LOCAL_SRC_FILES := hook.c
include $(BUILD_SHARED_LIBRARY)
ndk-build编译后生成的libhook.so,export LD_PRELOAD=&/data/local/tmp/hook.so&可以针对上面所列举的api进行hook。
二、摘自非虫:Android API Hook 之LD_PRELOAD
1. 在linker 中,LD_PRELOAD 的环境变量保存在一个全局的缓冲区中的,Hook的函数在整个程序的执行
会话中都是有效的,但不影响其它的会话。
2. Hook的函数可以是系统 API,也可以是其它动态链接库的函数。
3. Hook系统 API 时,在 Hook的代码中不能调用这个被 Hook的函数,否则程序会异常退出。
4. 想要使Hook对整个系统会话生效,可以在 Android系统启动配置文件中 init.rc 中声明 LD_PRELOAD
环境变量,目前发现有些软件是这么做的。
三、如何避免LD_PRELOAD带来的安全问题
摘自耗子的警惕UNIX下的LD_PRELOAD环境变量
不可否认,LD_PRELOAD是一个很难缠的问题。目前来说,要解决这个问题,只能想方设法让LD_PRELOAD失效。目前而言,有以下面两种方法可以让LD_PRELOAD失效。
1)通过静态链接。使用gcc的-static参数可以把libc.so.6静态链入执行程序中。但这也就意味着你的程序不再支持动态链接。
2)通过设置执行文件的setgid / setuid标志。在有SUID权限的执行文件,系统会忽略LD_PRELOAD环境变量。也就是说,如果你有以root方式运行的程序,最好设置上SUID权限。(如:chmod 4755 daemon)
1.警惕UNIX下的LD_PRELOAD环境变量
2.非虫:Android API Hook 之LD_PRELOAD
3.ldpreloadhook
已发表评论数()
&&登&&&陆&&
已收藏到推刊!
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见今日: 0|昨日: 0|帖子: 11404|会员: 3385|欢迎新会员:
总共1190条微博&&动态微博
分区版主: ,
子版块: , ,
记录旅途中的所见所闻所感,分享你的行程。
三言二语 沟通从此起航。
子版块: , ,
310 / 1034
音乐、影视、动漫一样都不能少子版块: , ,
357 / 1230
一句话,一种心情,一份感触。版主: , ,
展示自己的舞台。
那些最美的的风景,你怎可错过。版主:
发布计划,相约出游,找伴同行。
- 总计 16 人在线
- 最高记录是 2972 于 .
对于80后,我们总有太多的话要说。
如此反复如此老生常谈,因为他们处在社会的一个特殊的转型期。
他们出生在计划生育的年代,他们成长在一个中国经济突飞猛进的时期,他们身处一个知识信息大爆炸的时代,他们由现实世界过渡到互联网的虚拟世界,中国社会的华丽转身也总有他们的声音、他们的影子。
如今,80后最小的23岁,最大的33岁......
Powered by歌曲 Moon Flow 歌手 後X°
热卖大片12345678910最新上映12345678910
一首纯的.喜欢的话请打星星,谢谢!
热度 78390
53 人认为非常好听
被评为“好听”的歌将被顶到首页第一个位置
第一次推荐  
STWebPlayer
下载ST手机版( / )
相关专辑:{if typeof(oktext) != 'undefined'}<a data-action="ok" href="javascript:void(0)" class="u-btn2 u-btn2-2 u-btn2-2-h {if oktext.length${oktext}{/if}
{if typeof(cctext) != 'undefined'}<a data-action="cc" href="javascript:void(0)" class="u-btn2 u-btn2-1 u-btn2-1-h {if cctext.length${cctext}{/if}
该资源需付费使用,现在抢购即可无限畅听!
该资源为公益歌曲
捐赠任意金额(2~4999元)即可无限畅听下载
「梦想起航」 by TFboys
请输入您要捐赠的金额(2~4999元)
输入金额无效
{list plist as item}}

我要回帖

更多关于 moonlight 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信