—–我又回来csdn开始记流水账了
源码位置:https://github.com/zyq8709/DexHunter
配置工具:
4.4.3版本的nexus5手机
下载好的源码和编译环境
我们先谈用法:
置换源码中的dalvik\vm\native\dalvik_system_DexFile.cpp文件
然后 make libdvm 编译
用生成的libdvm.so替换系统中的/system/lib/libdvm.so即可
导入dexname文件 并push到data目录下 并chmod 777
dexname里面写的是加载dex的位置 和输出脱壳的dex的位置
这是dexhunter里面改变的代码dalvik_system_DexFile.cpp
加入的第一段代码
#include <asm/siginfo.h>
#include "libdex/DexClass.h"
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
static char dexname[100]={0};
static char dumppath[100]={0};
static bool readable=true;
static pthread_mutex_t read_mutex;
static bool flag=true;
static pthread_mutex_t mutex;
static bool timer_flag=true;
static timer_t timerId;
struct arg{
DvmDex* pDvmDex;
Object * loader;
}param;
void timer_thread(sigval_t)
{
timer_flag=false;
timer_delete(timerId);
ALOGI("GOT IT time up");
}
void* ReadThread(void *arg){
FILE *fp = NULL;
while (dexname[0]==0||dumppath[0]==0) {
fp=fopen("/data/dexname", "r");
if (fp==NULL) {
sleep(1);
continue;
}
fgets(dexname,99,fp);
dexname[strlen(dexname)-1]=0;
fgets(dumppath,99,fp);
dumppath[strlen(dumppath)-1]=0;
fclose(fp);
fp=NULL;
}
struct sigevent sev;
sev.sigev_notify=SIGEV_THREAD;
sev.sigev_value.sival_ptr=&timerId;
sev.sigev_notify_function=timer_thread;
sev.sigev_notify_attributes = NULL;
timer_create(CLOCK_REALTIME,&sev,&timerId);
struct itimerspec ts;
ts.it_value.tv_sec=5;
ts.it_value.tv_nsec=0;
ts.it_interval.tv_sec=0;
ts.it_interval.tv_nsec=0;
timer_settime(timerId,0,&ts,NULL);
return NULL;
}
void ReadClassDataHeader(const uint8_t** pData,
DexClassDataHeader *pHeader) {
pHeader->staticFieldsSize = readUnsignedLeb128(pData);
pHeader->instanceFieldsSize = readUnsignedLeb128(pData);
pHeader->directMethodsSize = readUnsignedLeb128(pData);
pHeader->virtualMethodsSize = readUnsignedLeb128(pData);
}
void ReadClassDataField(const uint8_t** pData, DexField* pField) {
pField->fieldIdx = readUnsignedLeb128(pData);
pField->accessFlags = readUnsignedLeb128(pData);
}
void ReadClassDataMethod(const uint8_t** pData, DexMethod* pMethod) {
pMethod->methodIdx = readUnsignedLeb128(pData);
pMethod->accessFlags = readUnsignedLeb128(pData);
pMethod->codeOff = readUnsignedLeb128(pData);
}
DexClassData* ReadClassData(const uint8_t** pData) {
DexClassDataHeader header;
if (*pData == NULL) {
return NULL;
}
ReadClassDataHeader(pData,&header);
size_t resultSize = sizeof(DexClassData) + (header.staticFieldsSize * sizeof(DexField)) + (header.instanceFieldsSize * sizeof(DexField)) + (header.directMethodsSize * sizeof(DexMethod)) + (header.virtualMethodsSize * sizeof(DexMethod));
DexClassData* result = (DexClassData*) malloc(resultSize);
if (result == NULL) {
return NULL;
}
uint8_t* ptr = ((uint8_t*) result) + sizeof(DexClassData);
result->header = header;
if (header.staticFieldsSize != 0) {
result->staticFields = (DexField*) ptr;
ptr += header.staticFieldsSize * sizeof(DexField);
} else {
result->staticFields = NULL;
}
if (header.instanceFieldsSize != 0) {
result->instanceFields = (DexField*) ptr;
ptr += header.instanceFieldsSize * sizeof(DexField);
} else {
result->instanceFields = NULL;
}
if (header.directMethodsSize != 0) {
result->directMethods = (DexMethod*) ptr;
ptr += header.directMethodsSize * sizeof(DexMethod);
} else {
result->directMethods = NULL;
}
if (header.virtualMethodsSize != 0) {
result->virtualMethods = (DexMethod*) ptr;
} else {
result->virtualMethods = NULL;
}
for (uint32_t i = 0; i < header.staticFieldsSize; i++) {
ReadClassDataField(pData, &result->staticFields[i]);
}
for (uint32_t i = 0; i < header.instanceFieldsSize; i++) {
ReadClassDataField(pData, &result->instanceFields[i]);
}
for (uint32_t i = 0; i < header.directMethodsSize; i++) {
ReadClassDataMethod(pData, &result->directMethods[i]);
}
for (uint32_t i = 0; i < header.virtualMethodsSize; i++) {
ReadClassDataMethod(pData, &result->virtualMethods[i]);
}
return result;
}
void writeLeb128(uint8_t ** ptr, uint32_t data)
{
while (true) {
uint8_t out = data & 0x7f;
if (out != data) {
*(*ptr)++ = out | 0x80;
data >>= 7;
} else {
*(*ptr)++ = out;
break;
}
}
}
uint8_t* EncodeClassData(DexClassData *pData, int& len)
{
len=0;
len+=unsignedLeb128Size(pData->header.staticFieldsSize);
len+=unsignedLeb128Size(pData->header.instanceFieldsSize);
len+=unsignedLeb128Size(pData->header.directMethodsSize);
len+=unsignedLeb128Size(pData->header.virtualMethodsSize);
if (pData->staticFields) {
for (uint32_t i = 0; i < pData->header.staticFieldsSize; i++) {
len+=unsignedLeb128Size(pData->staticFields[i].fieldIdx);
len+=unsignedLeb128Size(pData->staticFields[i].accessFlags);
}
}
if (pData->instanceFields) {
for (uint32_t i = 0; i < pData->header.instanceFieldsSize; i++) {
len+=unsignedLeb128Size(pData->instanceFields[i].fieldIdx);
len+=unsignedLeb128Size(pData->instanceFields[i].accessFlags);
}
}
if (pData->directMethods) {
for (uint32_t i=0; i<pData->header.directMethodsSize; i++) {
len+=unsignedLeb128Size(pData->directMethods[i].methodIdx);
len+=unsignedLeb128Size(pData->directMethods[i].accessFlags);
len+=unsignedLeb128Size(pData->directMethods[i].codeOff);
}
}
if (pData->virtualMethods) {
for (uint32_t i=0; i<pData->header.virtualMethodsSize; i++) {
len+=unsignedLeb128Size(pData->virtualMethods[i].methodIdx);
len+=unsignedLeb128Size(pData->virtualMethods[i].accessFlags);
len+=unsignedLeb128Size(pData->virtualMethods[i].codeOff);
}
}
uint8_t * store = (uint8_t *) malloc(len);
if (!store) {
return NULL;
}
uint8_t * result=store;
writeLeb128(&store,pData->header.staticFieldsSize);
writeLeb128(&store,pData->header.instanceFieldsSize);
writeLeb128(&store,pData->header.directMethodsSize);
writeLeb128(&store,pData->header.virtualMethodsSize);
if (pData->staticFields) {
for (uint32_t i = 0; i < pData->header.staticFieldsSize; i++) {
writeLeb128(&store,pData->staticFields[i].fieldIdx);
writeLeb128(&store,pData->staticFields[i].accessFlags);
}
}
if (pData->instanceFields) {
for (uint32_t i = 0; i < pData->header.instanceFieldsSize; i++) {
writeLeb128(&store,pData->instanceFields[i].fieldIdx);
writeLeb128(&store,pData->instanceFields[i].accessFlags);
}
}
if (pData->directMethods) {
for (uint32_t i=0; i<pData->header.directMethodsSize; i++) {
writeLeb128(&store,pData->directMethods[i].methodIdx);
writeLeb128(&store,pData->directMethods[i].accessFlags);
writeLeb128(&store,pData->directMethods[i].codeOff);
}
}
if (pData->virtualMethods) {
for (uint32_t i=0; i<pData->header.virtualMethodsSize; i++) {
writeLeb128(&store,pData->virtualMethods[i].methodIdx);
writeLeb128(&store,pData->virtualMethods[i].accessFlags);
writeLeb128(&store,pData->virtualMethods[i].codeOff);
}
}
free(pData);
return result;
}
uint8_t* codeitem_end(const u1** pData)
{
uint32_t num_of_list = readUnsignedLeb128(pData);
for (;num_of_list>0;num_of_list--) {
int32_t num_of_handlers=readSignedLeb128(pData);
int num=num_of_handlers;
if (num_of_handlers<=0) {
num=-num_of_handlers;
}
for (; num > 0; num--) {
readUnsignedLeb128(pData);
readUnsignedLeb128(pData);
}
if (num_of_handlers<=0) {
readUnsignedLeb128(pData);
}
}
return (uint8_t*)(*pData);
}
void* DumpClass(void *parament)
{
while (timer_flag) {
sleep(5);
}
DvmDex* pDvmDex=((struct arg*)parament)->pDvmDex;
Object *loader=((struct arg*)parament)->loader;
DexFile* pDexFile=pDvmDex->pDexFile;
MemMapping * mem=&pDvmDex->memMap;
u4 time=dvmGetRelativeTimeMsec();
ALOGI("GOT IT begin: %d ms",time);
char *path = new char[100];
strcpy(path,dumppath);
strcat(path,"classdef");
FILE *fp = fopen(path, "wb+");
strcpy(path,dumppath);
strcat(path,"extra");
FILE *fp1 = fopen(path,"wb+");
uint32_t mask=0x3ffff;
char padding=0;
const char* header="Landroid";
unsigned int num_class_defs=pDexFile->pHeader->classDefsSize;
uint32_t total_pointer = mem->length-uint32_t(pDexFile->baseAddr-(const u1*)mem->addr);
uint32_t rec=total_pointer;
while (total_pointer&3) {
total_pointer++;
}
int inc=total_pointer-rec;
uint32_t start = pDexFile->pHeader->classDefsOff+sizeof(DexClassDef)*num_class_defs;
uint32_t end = (uint32_t)((const u1*)mem->addr+mem->length-pDexFile->baseAddr);
for (size_t i=0;i<num_class_defs;i++)
{
bool need_extra=false;
ClassObject * clazz=NULL;
const u1* data=NULL;
DexClassData* pData = NULL;
bool pass=false;
const DexClassDef *pClassDef = dexGetClassDef(pDvmDex->pDexFile, i);
const char *descriptor = dexGetClassDescriptor(pDvmDex->pDexFile,pClassDef);
if(!strncmp(header,descriptor,8)||!pClassDef->classDataOff)
{
pass=true;
goto classdef;
}
clazz = dvmDefineClass(pDvmDex, descriptor, loader);
if (!clazz) {
continue;
}
ALOGI("GOT IT class: %s",descriptor);
if (!dvmIsClassInitialized(clazz)) {
if(dvmInitClass(clazz)){
ALOGI("GOT IT init: %s",descriptor);
}
}
if(pClassDef->classDataOff<start || pClassDef->classDataOff>end)
{
need_extra=true;
}
data=dexGetClassData(pDexFile,pClassDef);
pData = ReadClassData(&data);
if (!pData) {
continue;
}
if (pData->directMethods) {
for (uint32_t i=0; i<pData->header.directMethodsSize; i++) {
Method *method = &(clazz->directMethods[i]);
uint32_t ac = (method->accessFlags) & mask;
ALOGI("GOT IT direct method name %s.%s",descriptor,method->name);
if (!method->insns||ac&ACC_NATIVE) {
if (pData->directMethods[i].codeOff) {
need_extra = true;
pData->directMethods[i].accessFlags=ac;
pData->directMethods[i].codeOff=0;
}
continue;
}
u4 codeitem_off = u4((const u1*)method->insns-16-pDexFile->baseAddr);
if (ac != pData->directMethods[i].accessFlags)
{
ALOGI("GOT IT method ac");
need_extra=true;
pData->directMethods[i].accessFlags=ac;
}
if (codeitem_off!=pData->directMethods[i].codeOff&&((codeitem_off>=start&&codeitem_off<=end)||codeitem_off==0)) {
ALOGI("GOT IT method code");
need_extra=true;
pData->directMethods[i].codeOff=codeitem_off;
}
if ((codeitem_off<start || codeitem_off>end) && codeitem_off!=0) {
need_extra=true;
pData->directMethods[i].codeOff = total_pointer;
DexCode *code = (DexCode*)((const u1*)method->insns-16);
uint8_t *item=(uint8_t *) code;
int code_item_len = 0;
if (code->triesSize) {
const u1 * handler_data = dexGetCatchHandlerData(code);
const u1** phandler=(const u1**)&handler_data;
uint8_t * tail=codeitem_end(phandler);
code_item_len = (int)(tail-item);
}else{
code_item_len = 16+code->insnsSize*2;
}
ALOGI("GOT IT method code changed");
fwrite(item,1,code_item_len,fp1);
fflush(fp1);
total_pointer+=code_item_len;
while (total_pointer&3) {
fwrite(&padding,1,1,fp1);
fflush(fp1);
total_pointer++;
}
}
}
}
if (pData->virtualMethods) {
for (uint32_t i=0; i<pData->header.virtualMethodsSize; i++) {
Method *method = &(clazz->virtualMethods[i]);
uint32_t ac = (method->accessFlags) & mask;
ALOGI("GOT IT virtual method name %s.%s",descriptor,method->name);
if (!method->insns||ac&ACC_NATIVE) {
if (pData->virtualMethods[i].codeOff) {
need_extra = true;
pData->virtualMethods[i].accessFlags=ac;
pData->virtualMethods[i].codeOff=0;
}
continue;
}
u4 codeitem_off = u4((const u1 *)method->insns - 16 - pDexFile->baseAddr);
if (ac != pData->virtualMethods[i].accessFlags)
{
ALOGI("GOT IT method ac");
need_extra=true;
pData->virtualMethods[i].accessFlags=ac;
}
if (codeitem_off!=pData->virtualMethods[i].codeOff&&((codeitem_off>=start&&codeitem_off<=end)||codeitem_off==0)) {
ALOGI("GOT IT method code");
need_extra=true;
pData->virtualMethods[i].codeOff=codeitem_off;
}
if ((codeitem_off<start || codeitem_off>end)&&codeitem_off!=0) {
need_extra=true;
pData->virtualMethods[i].codeOff = total_pointer;
DexCode *code = (DexCode*)((const u1*)method->insns-16);
uint8_t *item=(uint8_t *) code;
int code_item_len = 0;
if (code->triesSize) {
const u1 *handler_data = dexGetCatchHandlerData(code);
const u1** phandler=(const u1**)&handler_data;
uint8_t * tail=codeitem_end(phandler);
code_item_len = (int)(tail-item);
}else{
code_item_len = 16+code->insnsSize*2;
}
ALOGI("GOT IT method code changed");
fwrite(item,1,code_item_len,fp1);
fflush(fp1);
total_pointer+=code_item_len;
while (total_pointer&3) {
fwrite(&padding,1,1,fp1);
fflush(fp1);
total_pointer++;
}
}
}
}
classdef:
DexClassDef temp=*pClassDef;
uint8_t *p = (uint8_t *)&temp;
if (need_extra) {
ALOGI("GOT IT classdata before");
int class_data_len = 0;
uint8_t *out = EncodeClassData(pData,class_data_len);
if (!out) {
continue;
}
temp.classDataOff = total_pointer;
fwrite(out,1,class_data_len,fp1);
fflush(fp1);
total_pointer+=class_data_len;
while (total_pointer&3) {
fwrite(&padding,1,1,fp1);
fflush(fp1);
total_pointer++;
}
free(out);
ALOGI("GOT IT classdata written");
}else{
if (pData) {
free(pData);
}
}
if (pass) {
temp.classDataOff=0;
temp.annotationsOff=0;
}
ALOGI("GOT IT classdef");
fwrite(p, sizeof(DexClassDef), 1, fp);
fflush(fp);
}
fclose(fp1);
fclose(fp);
strcpy(path,dumppath);
strcat(path,"whole.dex");
fp = fopen(path,"wb+");
rewind(fp);
int fd=-1;
int r=-1;
int len=0;
char *addr=NULL;
struct stat st;
strcpy(path,dumppath);
strcat(path,"part1");
fd=open(path,O_RDONLY,0666);
if (fd==-1) {
return NULL;
}
r=fstat(fd,&st);
if(r==-1){
close(fd);
return NULL;
}
len=st.st_size;
addr=(char*)mmap(NULL,len,PROT_READ,MAP_PRIVATE,fd,0);
fwrite(addr,1,len,fp);
fflush(fp);
munmap(addr,len);
close(fd);
strcpy(path,dumppath);
strcat(path,"classdef");
fd=open(path,O_RDONLY,0666);
if (fd==-1) {
return NULL;
}
r=fstat(fd,&st);
if(r==-1){
close(fd);
return NULL;
}
len=st.st_size;
addr=(char*)mmap(NULL,len,PROT_READ,MAP_PRIVATE,fd,0);
fwrite(addr,1,len,fp);
fflush(fp);
munmap(addr,len);
close(fd);
strcpy(path,dumppath);
strcat(path,"data");
fd=open(path,O_RDONLY,0666);
if (fd==-1) {
return NULL;
}
r=fstat(fd,&st);
if(r==-1){
close(fd);
return NULL;
}
len=st.st_size;
addr=(char*)mmap(NULL,len,PROT_READ,MAP_PRIVATE,fd,0);
fwrite(addr,1,len,fp);
fflush(fp);
munmap(addr,len);
close(fd);
while (inc>0) {
fwrite(&padding,1,1,fp);
fflush(fp);
inc--;
}
strcpy(path,dumppath);
strcat(path,"extra");
fd=open(path,O_RDONLY,0666);
if (fd==-1) {
return NULL;
}
r=fstat(fd,&st);
if(r==-1){
close(fd);
return NULL;
}
len=st.st_size;
addr=(char*)mmap(NULL,len,PROT_READ,MAP_PRIVATE,fd,0);
fwrite(addr,1,len,fp);
fflush(fp);
munmap(addr,len);
close(fd);
fclose(fp);
delete path;
time=dvmGetRelativeTimeMsec();
ALOGI("GOT IT end: %d ms",time);
return NULL;
}
加入的第二段代码
//------------------------added begin----------------------//
int uid=getuid();
if (uid) {
if (readable) {
pthread_mutex_lock(&read_mutex);
if (readable) {
readable=false;
pthread_mutex_unlock(&read_mutex);
pthread_t read_thread;
pthread_create(&read_thread, NULL, ReadThread, NULL);
}else{
pthread_mutex_unlock(&read_mutex);
}
}
}
if(uid&&strcmp(dexname,"")){
char * res=strstr(pDexOrJar->fileName, dexname);
if (res&&flag) {
pthread_mutex_lock(&mutex);
if (flag) {
flag = false;
pthread_mutex_unlock(&mutex);
DexFile* pDexFile=pDvmDex->pDexFile;
MemMapping * mem=&pDvmDex->memMap;
char * temp=new char[100];
strcpy(temp,dumppath);
strcat(temp,"part1");
FILE *fp = fopen(temp, "wb+");
const u1 *addr = (const u1*)mem->addr;
int length=int(pDexFile->baseAddr+pDexFile->pHeader->classDefsOff-addr);
fwrite(addr,1,length,fp);
fflush(fp);
fclose(fp);
strcpy(temp,dumppath);
strcat(temp,"data");
fp = fopen(temp, "wb+");
addr = pDexFile->baseAddr+pDexFile->pHeader->classDefsOff+sizeof(DexClassDef)*pDexFile->pHeader->classDefsSize;
length=int((const u1*)mem->addr+mem->length-addr);
fwrite(addr,1,length,fp);
fflush(fp);
fclose(fp);
delete temp;
param.loader=loader;
param.pDvmDex=pDvmDex;
pthread_t dumpthread;
dvmCreateInternalThread(&dumpthread,"ClassDumper",DumpClass,(void*)¶m);
}else{
pthread_mutex_unlock(&mutex);
}
}
}
//------------------------added end----------------------//