看雪论坛作者ID:Umiade
加载
int xlen = lseek(fd, 0L, SEEK_END);
if (xlen < 0)
{
LOGE("[-] lseek error in xdlopen");
return NULL;
}
int xplen = xlen;
if (xplen < 0xA000)
xplen = 0xA000;
lseek(fd, 0L, SEEK_SET);
xbuf = (unsigned char*)((int)mmap(NULL, xplen, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) + PAGE_SIZE);
LOGD("fct size: 0x%8x\n", xlen % PAGE_SIZE == 0 ? xlen : xlen + PAGE_SIZE - xlen % PAGE_SIZE);
mprotect(xbuf, xlen % PAGE_SIZE == 0 ? xlen : xlen + PAGE_SIZE - xlen % PAGE_SIZE, PROT_READ | PROT_EXEC | PROT_WRITE);
{
"plt": [
{
"off": -384,
"foo": "_libc_init"
},
....
,
{
"off": -36,
"foo": "memcpy"
},
{
"off": -24,
"foo": "__cxa_begin_cleanup"
},
{
"off": -12,
"foo": "__cxa_type_match"
}
],
"got": [
{
"off": 13352,
"foo": "__stack_chk_guard_ptr"
},
{
"off": 13356,
"foo": "__sF"
}
],
"rodata": [
{
"off": 12232,
"foo": "[%s]"
},
{
"off": 12248,
"foo": "[+] dm patch success"
}
],
"bss": [
{
"off": 13528,
"foo": "0"
}
]
}
修复
struct sigaction sa = { 0 };
sa.sa_sigaction = &_segv_handler;
sa.sa_flags = SA_SIGINFO;
struct sigaction osa = { 0 };
sigaction(SIGSEGV, &sa, &osa);
__asm__
(
"mov r0, %0; \
ldr r2, [r0, #0x0]; \
ldr r1, [r0, #0x20]; \
mov r8, r1; \
ldr r1, [r0, #0x24]; \
mov r9, r1; \
ldr r1, [r0, #0x28]; \
mov r10, r1; \
ldr r1, [r0, #0x2C]; \
mov r11, r1; \
ldr r1, [r0, #0x30]; \
mov r12, r1; \
ldr r1, [r0, #0x34]; \
mov r13, r1; \
ldr r1, [r0, #0x38]; \
mov r14, r1; \
ldr r1, [r0, #0x3C]; \
mov r3, #1; \
orr r1, r3; \
push {r1}; \
push {r2}; \
ldr r1, [r0, #0x4]; \
ldr r2, [r0, #0x8]; \
ldr r3, [r0, #0xC]; \
ldr r4, [r0, #0x10]; \
ldr r5, [r0, #0x14]; \
ldr r6, [r0, #0x18]; \
ldr r7, [r0, #0x1C]; \
pop {r0}; \
pop {pc};"
:\
: "r"(x_reg) \
:
);
for (idx = 0; xpltInfo[idx].offset != 0; idx++)
{
for (int off = 0x20; off <= 0x5C; off += 4)
{
if (*((unsigned int*)((unsigned int)ctx + off)) == xpltInfo[idx].offset + (int)(g_xi->buffer))
{
void* imp = dlsym(RTLD_DEFAULT, xpltInfo[idx].value);
LOGD("[*] Fix plt %s=0x%08X\n", xpltInfo[idx].value, imp);
*((unsigned int*)((unsigned int)ctx + off)) = (unsigned int)imp;
if ((unsigned int)imp % 2 == 1)
*((unsigned int*)((unsigned int)ctx + 0x60)) = *((unsigned int*)((unsigned int)ctx + 0x60)) | 0b100000;
else
*((unsigned int*)((unsigned int)ctx + 0x60)) = *((unsigned int*)((unsigned int)ctx + 0x60)) & 0b11111111111111111111111111011111;
}
}
}
if (strcmp(xgotInfo[idx].value, "__stack_chk_guard_ptr") == 0)
{
unsigned int* scgp = (unsigned int*)malloc(sizeof(int));
memset(scgp, 0, sizeof(int));
LOGD("[*] Fix got %s=0x%08X\n", xgotInfo[idx].value, scgp);
*((unsigned int*)((unsigned int)ctx + off)) = (int)&scgp;
}
else if (strcmp(xgotInfo[idx].value, "__sF") == 0)
{
unsigned int* sf = (unsigned int*)malloc(sizeof(int));
memset(sf, 0, sizeof(int));
*sf = (int)stderr - 0xA8;
LOGD("[*] Fix got %s=0x%08X\n", xgotInfo[idx].value, sf);
*((unsigned int*)((unsigned int)ctx + off)) = (unsigned int)sf;
}
开源地址
运行demo
./xlinker /data/local/tmp/dm_bin /data/local/tmp/dm.plk
存在的坑
目前仅仅实现了对bin文件的dlopen;
未实现自定义的dlsym,demo代码的main函数偏移是写死的;
对于rodata,存在由于文件过小,有部分内容与text段尾部的代码处于同一页的情况,demo中通过直接修改二进制的形式将访问rodata的偏移量增大了一个页的大小;
琢磨的时候代码是想到哪写到哪,所以可能会有比较“神秘”的声明和注释,无视即可;
由于指令和数据的分离,可以在加载、修复时加入加解密、压缩等操作,勉强当成一个简单的加固工具来用,但这种实现是否存在性能上的问题还有待验证。
看雪ID:Umiade
https://bbs.pediy.com/user-670564.htm
推荐文章++++