/
/
获取libc的基地址
intptr_t get_libc_base(pid_t pid)
{
intptr_t libcAddr;
char
*
buf;
char
*
end;
FILE
*
fd
=
fopen(
"/proc/self/maps"
,
"r"
);
if
(!fd)
{
printf(
"open maps error!"
);
exit(
1
);
}
buf
=
(char
*
) malloc(
0x100
);
do{
fgets(buf,
0x100
, fd);
}
while
(!strstr(buf,
"libc-"
));
end
=
strchr(buf,
'-'
);
libcAddr
=
strtol(buf, &end,
16
);
/
/
printf(
"The process %d's libcbase is: 0x%lx\n"
, pid, libcAddr);
fclose(fd);
return
libcAddr;
}
/
/
获取目标函数的地址
intptr_t get_target_addr(intptr_t libc_base, const char
*
func_name)
{
intptr_t funcAddr;
funcAddr
=
(size_t)dlsym(
0
, func_name);
funcAddr
-
=
get_libc_base(getpid());
funcAddr
+
=
libc_base;
/
/
printf(
"function %s address is: 0x%lx\n"
, func_name, funcAddr);
return
funcAddr;
}
/
/
获取目标函数前几条指令的长度
int
get_asm_len(intptr_t target)
{
csh handle;
cs_insn
*
insn;
size_t count;
char code[
30
]
=
{
0
};
int
rv;
memcpy((void
*
)code, (void
*
)target,
30
);
if
(cs_open(CS_ARCH_X86, CS_MODE_64, &handle))
{
printf(
"Error: cs_open\n"
);
return
-
1
;
}
count
=
cs_disasm(handle, code,
30
,
0
,
0
, &insn);
if
(count)
{
for
(size_t i
=
0
; i < count; i
+
+
)
{
if
(insn[i].address >
=
14
)
{
rv
=
insn[i].address;
break
;
}
}
cs_free(insn, count);
}
else
{
printf(
"Error: cs_disasm\n"
);
return
-
1
;
}
cs_close(&handle);
return
rv;
}
/
/
替换目标函数的前
len
个字节,使之跳转到hook函数
void change_bytes(intptr_t addr, const char code[],
int
len
)
{
memcpy((void
*
)addr, code,
len
);
}
void func_hook(const char
*
funcname, void
*
hook_func, void
*
*
origin_func)
{
intptr_t libc_base
=
get_libc_base(getpid());
intptr_t target_addr
=
get_target_addr(libc_base, funcname);
/
/
根据目标函数的地址确定目标函数所在的页,并将该页的权限改为可读可写可执行
intptr_t page_start
=
target_addr &
0xfffffffff000
;
mprotect((void
*
)page_start,
0x1000
, PROT_READ|PROT_WRITE|PROT_EXEC);
int
asm_len
=
get_asm_len(target_addr);
if
(asm_len <
=
0
)
{
printf(
"Error: get_asm_len\n"
);
exit(
-
1
);
}
char
*
temp_func
=
(char
*
)mmap(NULL,
4096
, PROT_WRITE|PROT_EXEC|PROT_READ, MAP_ANON|MAP_PRIVATE,
-
1
,
0
);
memcpy((void
*
)temp_func, (void
*
)target_addr, asm_len);
intptr_t y
=
(intptr_t)target_addr
+
asm_len;
/
/
构造push&ret跳转,填入目标地址
char jmp_code[
14
]
=
{
0x68
,y&
0xff
,(y&
0xff00
)>>
8
,(y&
0xff0000
)>>
16
,(y&
0xff000000
)>>
24
,
0xC7
,
0x44
,
0x24
,
0x04
,(y&
0xff00000000
)>>
32
,(y&
0xff0000000000
)>>
40
,(y&
0xff000000000000
)>>
48
,
(y&
0xff00000000000000
)>>
56
,
0xC3
};
memcpy((void
*
)(temp_func
+
asm_len), (void
*
)jmp_code,
14
);
*
origin_func
=
(void
*
)temp_func;
intptr_t x
=
(intptr_t)hook_func;
char hard_code[
14
]
=
{
0x68
,x&
0xff
,(x&
0xff00
)>>
8
,(x&
0xff0000
)>>
16
,(x&
0xff000000
)>>
24
,
0xC7
,
0x44
,
0x24
,
0x04
,(x&
0xff00000000
)>>
32
,(x&
0xff0000000000
)>>
40
,(x&
0xff000000000000
)>>
48
,
(x&
0xff00000000000000
)>>
56
,
0xC3
};
change_bytes(target_addr, hard_code,
14
);
}
static
FILE
*
(
*
origin_fopen)(const char
*
filename, const char
*
mod);
static
int
(
*
origin_fclose)(
FILE
*
fp);
static
FILE
*
fopen_hook(const char
*
filename, const char
*
mod)
{
FILE
*
rv
=
origin_fopen(filename, mod);
printf(
"fopen(\"%s\", \"%s\")\n\treturn: %p\n"
, filename, mod, rv);
return
rv;
}
static
int
fclose_hook(
FILE
*
fp)
{
int
rv
=
origin_fclose(fp);
printf(
"fclose(%p)\n\treturn: %d\n"
, fp, rv);
return
rv;
}
/
/
so被加载后会首先执行这里的代码
__attribute__((constructor))
void load()
{
func_hook(
"fopen"
, (void
*
)fopen_hook, (void
*
*
)&origin_fopen);
func_hook(
"fclose"
, (void
*
)fclose_hook, (void
*
*
)&origin_fclose);
printf(
"inject suceessfully\n"
);
}