exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

SyscalltableAMD64EN.txt

SyscalltableAMD64EN.txt
Posted Oct 18, 2006
Authored by pouik

Whitepaper titled "How to get sys_call_table on amd64 under Linux".

tags | paper
systems | linux
SHA-256 | 11d6399ff6d685f568357529150b4e34ee0ce5665b5ae70367a50f78b5f900af

SyscalltableAMD64EN.txt

Change Mirror Download
|=-----------------=[ Obtain sys_call_table on amd64(x86_64) ]=---------------=|
|=----------------------------------------------------------------------------=|
|=-----------------------=[ pouik <pouik@zeppoo.net> ]=----------------------=|


--[ Summary
1 - Introduction
2 - IDT
3 - System_call
4 - Sys_call_table
5 - Test
6 - Conclusion

--[ 1 Introduction

Some people remember the article written by sd & devik in phrack 58 [1] which
introduce for the first time (or it's silvio?) the way to find the
sys_call_table on X86 in userland with /dev/(k)mem and how to use it, in order
to create rootkits on Linux.

With this article you'll be able to obtain the sys_call_table on archi Amd64

Most Linux distributions have its kernel compiled with option
CONFIG_IA32_EMULATION=y which, simply ensure the compatibility between
architecture 32 bits and 64 bits.

Kernel developers' have inserted the ia32_sys_call_table and this is very
interesting... so ladies and gentlemens go to next part ! in order to know
why :p


--[ 2 IDT

On x86, we can obtain IDT (Interrupt Descriptor Table) with asm instruction
asm("sidt %0" : "=m" (idtr)); which fill the structure idtr :
struct {
unsigned short limit;
unsigned int base;
} __attribute__((packed)) idtr;


On amd64, the base needs 8 octects (and not 4 octets), so we use the next
structure :
struct {
unsigned short limit;
unsigned long base;
} __attribute__((packed)) idtr;

--[ 3 System_call

Then, the idea of sd & devik was to obtain the IDT corresponding to
int $0x80 :
readkmem (&idt,idtr.base+8*0x80,sizeof(idt));
sys_call_off = (idt.off2 << 16) | idt.off1;


Here that's ok, but we must read 16 bits:
readkmem (&idt,idtr.base+16*0x80,sizeof(idt));
sys_call_off = (idt.off2 << 16) | idt.off1;

Take a moment, in the introduction, we indicate that kernel developers have
inserted a compatibility with software 32 bits, and here, the syscall should be
on ia32 :
promethee kernel # pwd
/usr/src/linux/arch/x86_64/kernel
promethee kernel # grep SYSCALL_VECTOR *
i8259.c: if (vector != IA32_SYSCALL_VECTOR)
io_apic.c: if (current_vector == IA32_SYSCALL_VECTOR)
traps.c: set_system_gate(IA32_SYSCALL_VECTOR, ia32_syscall);

So bingo, we obtain the system_call which is,in reality, ia32_syscall. :)

--[ 4 Sys_call_table


Now that we have ia32_syscall, keep a close eye on execution:

(gdb) disassemble ia32_syscall
Dump of assembler code for function ia32_syscall:
0xffffffff8021f6fc <ia32_syscall+0>: swapgs
0xffffffff8021f6ff <ia32_syscall+3>: sti
0xffffffff8021f700 <ia32_syscall+4>: mov %eax,%eax
0xffffffff8021f702 <ia32_syscall+6>: push %rax
0xffffffff8021f703 <ia32_syscall+7>: cld
0xffffffff8021f704 <ia32_syscall+8>: sub $0x48,%rsp
0xffffffff8021f708 <ia32_syscall+12>: mov %rdi,0x40(%rsp)
0xffffffff8021f70d <ia32_syscall+17>: mov %rsi,0x38(%rsp)
0xffffffff8021f712 <ia32_syscall+22>: mov %rdx,0x30(%rsp)
0xffffffff8021f717 <ia32_syscall+27>: mov %rcx,0x28(%rsp)
0xffffffff8021f71c <ia32_syscall+32>: mov %rax,0x20(%rsp)
0xffffffff8021f721 <ia32_syscall+37>: mov %gs:0x10,%r10
0xffffffff8021f72a <ia32_syscall+46>: sub $0x1fd8,%r10
0xffffffff8021f731 <ia32_syscall+53>: orl $0x2,0x14(%r10)
0xffffffff8021f736 <ia32_syscall+58>: testl $0x181,0x10(%r10)
0xffffffff8021f73e <ia32_syscall+66>: jne 0xffffffff8021f768 <ia32_tracesys>
End of assembler dump.

(gdb) disassemble ia32_tracesys
Dump of assembler code for function ia32_tracesys:
0xffffffff8021f768 <ia32_tracesys+0>: sub $0x30,%rsp
0xffffffff8021f76c <ia32_tracesys+4>: mov %rbx,0x28(%rsp)
0xffffffff8021f771 <ia32_tracesys+9>: mov %rbp,0x20(%rsp)
0xffffffff8021f776 <ia32_tracesys+14>: mov %r12,0x18(%rsp)
0xffffffff8021f77b <ia32_tracesys+19>: mov %r13,0x10(%rsp)
0xffffffff8021f780 <ia32_tracesys+24>: mov %r14,0x8(%rsp)
0xffffffff8021f785 <ia32_tracesys+29>: mov %r15,(%rsp)
0xffffffff8021f789 <ia32_tracesys+33>: movq $0xffffffffffffffda,0x50(%rsp)
0xffffffff8021f792 <ia32_tracesys+42>: mov %rsp,%rdi
0xffffffff8021f795 <ia32_tracesys+45>: callq 0xffffffff8020c684 <syscall_trace_enter>
0xffffffff8021f79a <ia32_tracesys+50>: mov 0x30(%rsp),%r11
0xffffffff8021f79f <ia32_tracesys+55>: mov 0x38(%rsp),%r10
0xffffffff8021f7a4 <ia32_tracesys+60>: mov 0x40(%rsp),%r9
0xffffffff8021f7a9 <ia32_tracesys+65>: mov 0x48(%rsp),%r8
0xffffffff8021f7ae <ia32_tracesys+70>: mov 0x58(%rsp),%rcx
0xffffffff8021f7b3 <ia32_tracesys+75>: mov 0x60(%rsp),%rdx
0xffffffff8021f7b8 <ia32_tracesys+80>: mov 0x68(%rsp),%rsi
0xffffffff8021f7bd <ia32_tracesys+85>: mov 0x70(%rsp),%rdi
0xffffffff8021f7c2 <ia32_tracesys+90>: mov 0x78(%rsp),%rax
0xffffffff8021f7c7 <ia32_tracesys+95>: mov (%rsp),%r15
0xffffffff8021f7cb <ia32_tracesys+99>: mov 0x8(%rsp),%r14
0xffffffff8021f7d0 <ia32_tracesys+104>: mov 0x10(%rsp),%r13
0xffffffff8021f7d5 <ia32_tracesys+109>: mov 0x18(%rsp),%r12
0xffffffff8021f7da <ia32_tracesys+114>: mov 0x20(%rsp),%rbp
0xffffffff8021f7df <ia32_tracesys+119>: mov 0x28(%rsp),%rbx
0xffffffff8021f7e4 <ia32_tracesys+124>: add $0x30,%rsp
0xffffffff8021f7e8 <ia32_tracesys+128>: jmpq 0xffffffff8021f740 <ia32_do_syscall>
End of assembler dump.

(gdb) disassemble ia32_do_syscall
Dump of assembler code for function ia32_do_syscall:
0xffffffff8021f740 <ia32_do_syscall+0>: cmp $0x13c,%eax
0xffffffff8021f745 <ia32_do_syscall+5>: ja 0xffffffff8021f7ed <ia32_badsys>
0xffffffff8021f74b <ia32_do_syscall+11>: mov %edi,%r8d
0xffffffff8021f74e <ia32_do_syscall+14>: mov %ebp,%r9d
0xffffffff8021f751 <ia32_do_syscall+17>: xchg %ecx,%esi
0xffffffff8021f753 <ia32_do_syscall+19>: mov %ebx,%edi
0xffffffff8021f755 <ia32_do_syscall+21>: mov %edx,%edx
0xffffffff8021f757 <ia32_do_syscall+23>: callq *0xffffffff804f6110(,%rax,8)
End of assembler dump.

After visiting ia32_tracesys, we jump on ia32_di_syscall, which makes a call :
callq *0xffffffff804f6110(,%rax,8)

promethee linux # grep ffffffff804f6110 /boot/System.map
ffffffff804f6110 R ia32_sys_call_table

And that work, we obtain the ia32_sys_call_table :p
In order to obtain it from system_call, sd & devik read 256 characters and
search pattern "\xff\x14\x85":
readkmem (sc_asm,sys_call_off,CALLOFF);
p = (char*)memmem (sc_asm,CALLOFF,"\xff\x14\x85",3);
sct = *(unsigned*)(p+3);
Why don't apply this method?

(gdb) x/xw ia32_do_syscall+23
0xffffffff8021f757 <ia32_do_syscall+23>: 0x10c514ff

We just search pattern "\xff\x14\xc5" from ia32_syscall.

If you have understood until then, you think, perhaps,there are errors.
Indeed, we normally have a jump to do with ia32_tracesys in order to arrive
in ia32_dosyscall. And it's right... but we can use the fact that these
functions are consecutive in memory for jump tracesys.

We obtain :
readkmem (sc_asm,sys_call_off,CALLOFF);
p = (char*)memmem (sc_asm,CALLOFF,"\xff\x14\xc5",3);
sct = *(unsigned long*)(p+3);
sct = (sct & 0x00000000ffffffff) | 0xffffffff00000000;

We apply a mask in order to ignore useless informations.

Bonus Track :
An other way to find ia32_sys_call_table is using the function walk_krstab
writing in phalanx rootkit because :
promethee linux # grep ia32_sys_call_table /boot/System.map
ffffffff804f6110 R ia32_sys_call_table
ffffffff8055feb0 r __ksymtab_ia32_sys_call_table
ffffffff8056c9d0 r __kstrtab_ia32_sys_call_table
For more informations, please look at the previous article.

--[ 5 Test


promethee linux # grep ia32_syscall /boot/System.map
ffffffff8021f6fc T ia32_syscall
ffffffff804f6af8 r ia32_syscall_end
promethee linux # grep ia32_sys_call_table /boot/System.map
ffffffff804f6110 R ia32_sys_call_table
ffffffff8055feb0 r __ksymtab_ia32_sys_call_table
ffffffff8056c9d0 r __kstrtab_ia32_sys_call_table

Try the first method :

promethee linux # zeppoo -s -d /dev/mem
Kernel : 2.6.17.11
Kernel : 2.617110
proc : x86_64
KERNEL_START 0xffffffff80000000
KERNEL_END 0xffffffff81000000
PAGE_OFFSET 0xffff810000000000
PAGE_MAX 0xffffffffffffffff
Memory : /dev/mem
IDTR BASE 0xffffffff8067e000 LIMIT 0xfff
idt80: flags = 238 flags=EE sel=10 off1=f6fc off2=8021
SYSTEM_CALL : 0xffffffff8021f6fc
Sys Call Table 0xffffffff804f6110

With the second method :

promethee linux # zeppoo -s -d /dev/mem -m
Kernel : 2.6.17.11
Kernel : 2.617110
proc : x86_64
KERNEL_START 0xffffffff80000000
KERNEL_END 0xffffffff81000000
PAGE_OFFSET 0xffff810000000000
PAGE_MAX 0xffffffffffffffff
Memory : /dev/mem
IDTR BASE 0xffffffff8067e000 LIMIT 0xfff
idt80: flags = 238 flags=EE sel=10 off1=f6fc off2=8021
SYSTEM_CALL : 0xffffffff8021f6fc
????kstrtab = 0xffffffff8056c9d0
??????Sys Call Table 0xffffffff804f6110

--[ 6 Conclusion


So, it's the end of this small article, the source code is avaible on
http://www.zeppoo.netand on the svn (repertory libzeppoo)
'svn checkout https://subversion.cru.fr/zeppoo/trunk/ zeppoo'.

Now that you have the sys_call_table, techniques which work on i386
can work on amd64...:)


Reference :
[1] http://phrack.org/archives/58/p58-0x07

Thanks :
Yperite, n0name, tbowan et aryliin pour me supporter :p

Translated by Yperite (aime pas les chauSettes)

"End of your world, the beginning of mine"
Login or Register to add favorites

File Archive:

March 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Mar 1st
    16 Files
  • 2
    Mar 2nd
    0 Files
  • 3
    Mar 3rd
    0 Files
  • 4
    Mar 4th
    0 Files
  • 5
    Mar 5th
    0 Files
  • 6
    Mar 6th
    0 Files
  • 7
    Mar 7th
    0 Files
  • 8
    Mar 8th
    0 Files
  • 9
    Mar 9th
    0 Files
  • 10
    Mar 10th
    0 Files
  • 11
    Mar 11th
    0 Files
  • 12
    Mar 12th
    0 Files
  • 13
    Mar 13th
    0 Files
  • 14
    Mar 14th
    0 Files
  • 15
    Mar 15th
    0 Files
  • 16
    Mar 16th
    0 Files
  • 17
    Mar 17th
    0 Files
  • 18
    Mar 18th
    0 Files
  • 19
    Mar 19th
    0 Files
  • 20
    Mar 20th
    0 Files
  • 21
    Mar 21st
    0 Files
  • 22
    Mar 22nd
    0 Files
  • 23
    Mar 23rd
    0 Files
  • 24
    Mar 24th
    0 Files
  • 25
    Mar 25th
    0 Files
  • 26
    Mar 26th
    0 Files
  • 27
    Mar 27th
    0 Files
  • 28
    Mar 28th
    0 Files
  • 29
    Mar 29th
    0 Files
  • 30
    Mar 30th
    0 Files
  • 31
    Mar 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close