Skip to content

Commit

Permalink
Find the base address dynamically with libprocstat
Browse files Browse the repository at this point in the history
Signed-off-by:	Shawn Webb <shawn.webb@hardenedbsd.org>
Sponsored-by:	SoldierX
  • Loading branch information
lattera committed Aug 5, 2017
1 parent ed777f2 commit a10008d
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 24 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
SUBDIR+= include libhijack
SUBDIR+= include libhijack hijack

.include <bsd.subdir.mk>
6 changes: 5 additions & 1 deletion include/hijack.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@
#define F_NONE 0
#define F_DEBUG 1
#define F_DEBUG_VERBOSE 2
#define F_DYNAMIC_BASEADDR 4
#define F_NO_DYNAMIC_BASEADDR 8
#define F_FOUND_BASEDIR 16
#define F_DEFAULT (F_DYNAMIC_BASEADDR)

#define V_NONE 0
#define V_BASEADDR 1
Expand Down Expand Up @@ -156,7 +160,7 @@ typedef CBRESULT (*linkmap_callback)(struct _hijack *, void *, char *, unsigned

int GetErrorCode(HIJACK *);
const char *GetErrorString(HIJACK *);
HIJACK *InitHijack(void);
HIJACK *InitHijack(unsigned int);
bool IsFlagSet(HIJACK *, unsigned int);
int ToggleFlag(HIJACK *, unsigned int);
void *GetValue(HIJACK *, int);
Expand Down
2 changes: 2 additions & 0 deletions libhijack/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ CFLAGS+= -I${.CURDIR}/../include \
-I/usr/src/libexec/rtld-elf/${MACHINE_ARCH} \
-D${MACHINE_ARCH} \
-DHIJACK_INTERNAL

LDADD= -lprocstat
MAN=

.include <bsd.lib.mk>
19 changes: 0 additions & 19 deletions libhijack/elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,25 +214,6 @@ search_mem(HIJACK *hijack, unsigned long funcaddr, size_t funcsz, void *data, si
return ((unsigned long)NULL);
}

int
init_hijack_system(HIJACK *hijack)
{
/* This probably ought to be in libhijack.c */
if (!IsAttached(hijack))
return (SetError(hijack, ERROR_NOTATTACHED));

if (init_elf_headers(hijack) != 0)
return (SetError(hijack, ERROR_SYSCALL));

if ((hijack->pltgot = find_pltgot(hijack)) == (unsigned long)NULL)
return (GetErrorCode(hijack));

find_link_map_addr(hijack);
hijack->linkhead = &(hijack->soe->linkmap);

return (SetError(hijack, ERROR_NONE));
}

unsigned long
find_func_addr_in_got(HIJACK *hijack, unsigned long pltaddr, unsigned long addr)
{
Expand Down
98 changes: 95 additions & 3 deletions libhijack/libhijack.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,16 @@
#include <sys/wait.h>
#include <sys/ptrace.h>

#include <sys/param.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <libprocstat.h>

#include "hijack.h"

static int resolve_base_address(HIJACK *);

/**
* Returns last reported error code
* @param hijack Pointer to HIJACK instance
Expand Down Expand Up @@ -88,20 +96,22 @@ GetErrorString(HIJACK *hijack)
* \ingroup libhijack
*/
EXPORTED_SYM HIJACK *
InitHijack(void)
InitHijack(unsigned int flags)
{
HIJACK *hijack;
unsigned long baseaddr = BASEADDR;

hijack = malloc(sizeof(HIJACK));
if (!(hijack))
return NULL;

memset(hijack, 0x00, sizeof(HIJACK));

if (flags == F_NONE)
flags = F_DEFAULT;

hijack->version = "0.7.0";

SetValue(hijack, V_BASEADDR, &baseaddr);
ToggleFlag(hijack, flags);

return (hijack);
}
Expand Down Expand Up @@ -442,3 +452,85 @@ LoadLibrary(HIJACK *hijack, char *lib)

return (load_library(hijack, lib));
}

static int
resolve_base_address(HIJACK *hijack)
{
struct procstat *ps;
struct kinfo_proc *p;
struct kinfo_vmentry *vm;
unsigned int i, cnt;
int err;

vm = NULL;
p = NULL;
err = ERROR_NONE;
cnt = 0;

ps = procstat_open_sysctl();
if (ps == NULL) {
SetError(hijack, ERROR_SYSCALL);
return (-1);
}

p = procstat_getprocs(ps, KERN_PROC_PID, hijack->pid, &cnt);
if (cnt == 0) {
err = ERROR_SYSCALL;
goto error;
}

cnt = 0;
vm = procstat_getvmmap(ps, p, &cnt);
if (cnt == 0) {
err = ERROR_SYSCALL;
goto error;
}

for (i = 0; i < cnt; i++) {
if ((vm[i].kve_protection & KVME_PROT_EXEC) == KVME_PROT_EXEC
&& vm[i].kve_type == KVME_TYPE_VNODE) {
hijack->baseaddr = (unsigned long)vm[i].kve_start;
break;
}
}

if (hijack->baseaddr == (unsigned long)NULL)
err = ERROR_NEEDED;

error:
if (vm != NULL)
procstat_freevmmap(ps, vm);
if (p != NULL)
procstat_freeprocs(ps, p);
procstat_close(ps);
return (err);
}

int
init_hijack_system(HIJACK *hijack)
{
int err;

if (!IsAttached(hijack))
return (SetError(hijack, ERROR_NOTATTACHED));

if ((hijack->flags & F_DYNAMIC_BASEADDR) == F_DYNAMIC_BASEADDR) {
err = SetError(hijack, resolve_base_address(hijack));
if (err)
return (err);
} else {
if (hijack->baseaddr == (unsigned long)NULL)
hijack->baseaddr = BASEADDR;
}

if (init_elf_headers(hijack) != 0)
return (SetError(hijack, ERROR_SYSCALL));

if ((hijack->pltgot = find_pltgot(hijack)) == (unsigned long)NULL)
return (GetErrorCode(hijack));

find_link_map_addr(hijack);
hijack->linkhead = &(hijack->soe->linkmap);

return (SetError(hijack, ERROR_NONE));
}

0 comments on commit a10008d

Please sign in to comment.