105 lines
2.7 KiB
C
105 lines
2.7 KiB
C
// "man modify_ldt"
|
|
|
|
#define _GNU_SOURCE
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <sys/syscall.h>
|
|
#include <sys/types.h>
|
|
#include <asm/ldt.h>
|
|
|
|
int main(void)
|
|
{
|
|
struct user_desc ldt[8 * 1024];
|
|
long rc;
|
|
|
|
//rc = syscall(123, (int) 0, (void *) ldt, (unsigned long) sizeof (ldt));
|
|
//printf("read syscall == %ld\n", rc);
|
|
|
|
char *str = malloc(64);
|
|
strcpy(str, "hello world!");
|
|
printf("&str == %p\n", str);
|
|
|
|
unsigned int fs = 0xFFFFFFFF;
|
|
__asm__ __volatile__ (
|
|
"xorl %%eax, %%eax \n\t"
|
|
"movw %%fs, %%ax \n\t"
|
|
: "=a" (fs)
|
|
);
|
|
|
|
printf("Current %%fs: 0x%X\n", fs);
|
|
|
|
struct user_desc *entry = ldt;
|
|
entry->entry_number = -1;
|
|
entry->base_addr = (unsigned long) str;
|
|
entry->limit = 64;
|
|
entry->seg_32bit = 1;
|
|
entry->contents = MODIFY_LDT_CONTENTS_DATA;
|
|
entry->read_exec_only = 0;
|
|
entry->limit_in_pages = 0;
|
|
entry->seg_not_present = 0;
|
|
entry->useable = 1;
|
|
|
|
printf("entry=%u, base=%p, limit=%u\n", entry->entry_number, (void *) entry->base_addr, entry->limit);
|
|
|
|
// modify_ldt
|
|
// rc = syscall(SYS_modify_ldt, (int) 1, (void *) entry, (unsigned long) sizeof (*entry));
|
|
// printf("write syscall == %ld\n", rc);
|
|
|
|
// set_thread_area
|
|
rc = syscall(SYS_set_thread_area, entry);
|
|
printf("write syscall == %ld\n", rc);
|
|
|
|
printf("entry==%d\n", (int) (entry->entry_number));
|
|
|
|
// this doesn't give you a user_desc struct back, I think it gives you the real LDT entry...?
|
|
// rc = syscall(SYS_modify_ldt, (int) 0, (void *) entry, (unsigned long) sizeof (*entry) * 128);
|
|
// printf("read syscall == %ld\n", rc);
|
|
|
|
// long i;
|
|
// for (i = 0; i < 128; i++, entry++)
|
|
// printf("entry=%u, base=%p, limit=%u\n", entry->entry_number, (void *) entry->base_addr, entry->limit);
|
|
|
|
// I have no idea why this needs the "<< 3 | 3", but it's probably
|
|
// specified in the Intel manuals. I got this from looking at how
|
|
// Wine does it.
|
|
__asm__ __volatile__ (
|
|
//"pushw %%ax\n\t"
|
|
//"popw %%fs \n\t"
|
|
"movw %%ax,%%fs \n\t"
|
|
:
|
|
: "a" ((entry->entry_number << 3) | 3)
|
|
);
|
|
|
|
fs = 0xFFFFFFFF;
|
|
__asm__ __volatile__ (
|
|
"xorl %%eax, %%eax \n\t"
|
|
"movw %%fs, %%ax \n\t"
|
|
: "=a" (fs)
|
|
);
|
|
|
|
printf("New %%fs: 0x%X\n", fs);
|
|
|
|
char newstr[16];
|
|
memset(newstr, '\0', sizeof (newstr));
|
|
__asm__ __volatile__ (
|
|
"movl %%fs:0,%%eax\n\t"
|
|
"movl %%eax,(%%edi)\n\t"
|
|
"movl %%fs:4,%%eax\n\t"
|
|
"movl %%eax,4(%%edi)\n\t"
|
|
"movl %%fs:8,%%eax\n\t"
|
|
"movl %%eax,8(%%edi)\n\t"
|
|
:
|
|
: "D" (newstr)
|
|
: "eax"
|
|
);
|
|
|
|
printf("copied string == '%s'\n", newstr);
|
|
|
|
return 0;
|
|
}
|
|
|
|
// end of ldt.c ...
|
|
|