Vous êtes sur la page 1sur 3

10/16/2016

Gilgalab

Hooking Linux 3 Syscalls


About

Categories

CVEs

Posts

Tags

HookingLinux3Syscalls
PublishedbyHenriqueon11January2013

Itistimeagaintostarthackingthekernelalittlebit.Inordertotrytobringsomememoriesbackandafterstealingthesuggestionfromafriend,Idecidedtotryto
hookthesyscallsintheLinuxKernel3seriesforthex64architecture.
Thecodepresentedbelowhasbeentestedonthekernelversion3.2.0andseemstoworkaboutfine.
SoletshavealookatthecodeandIwilldiscusssomepartsofitafter.
#include<linux/module.h>
#include<linux/init.h>
#include<linux/types.h>
#include<asm/uaccess.h>
#include<asm/cacheflush.h>
#include<linux/syscalls.h>
#include<linux/delay.h>//loops_per_jiffy

#defineCR0_WP0x00010000//WriteProtectBit(CR0:16)

/*Justsowedonottaintthekernel*/
MODULE_LICENSE("GPL")

void**syscall_table
unsignedlong**find_sys_call_table(void)

long(*orig_sys_open)(constchar__user*filename,intflags,intmode)

unsignedlong**find_sys_call_table(){

unsignedlongptr
unsignedlong*p

for(ptr=(unsignedlong)sys_close
ptr<(unsignedlong)&loops_per_jiffy
ptr+=sizeof(void*)){

p=(unsignedlong*)ptr

if(p[__NR_close]==(unsignedlong)sys_close){
printk(KERN_DEBUG"Foundthesys_call_table!!!\n")
return(unsignedlong**)p
}
}

returnNULL
}

longmy_sys_open(constchar__user*filename,intflags,intmode){
longret

ret=orig_sys_open(filename,flags,mode)
printk(KERN_DEBUG"file%shasbeenopenedwithmode%d\n",filename,mode)

returnret
}

staticint__initsyscall_init(void)
{
intret
unsignedlongaddr
unsignedlongcr0

syscall_table=(void**)find_sys_call_table()

if(!syscall_table){
printk(KERN_DEBUG"Cannotfindthesystemcalladdress\n")
return1
}

cr0=read_cr0()
write_cr0(cr0&~CR0_WP)

addr=(unsignedlong)syscall_table
ret=set_memory_rw(PAGE_ALIGN(addr)PAGE_SIZE,3)
if(ret){
printk(KERN_DEBUG"Cannotsetthememorytorw(%d)ataddr%16lX\n",ret,PAGE_ALIGN(addr)PAGE_SIZE)
}else{
printk(KERN_DEBUG"3pagessettorw")
}

orig_sys_open=syscall_table[__NR_open]

http://www.gilgalab.com.br/hacking/programming/linux/2013/01/11/Hooking-Linux-3-syscalls/

1/3

10/16/2016

Hooking Linux 3 Syscalls

syscall_table[__NR_open]=my_sys_open

write_cr0(cr0)

return0
}

staticvoid__exitsyscall_release(void)
{
unsignedlongcr0

cr0=read_cr0()
write_cr0(cr0&~CR0_WP)

syscall_table[__NR_open]=orig_sys_open

write_cr0(cr0)
}

module_init(syscall_init)
module_exit(syscall_release)

Letsfirsthavealookatthefind_syscall_tablefunction.
unsignedlong**find_sys_call_table(){

unsignedlongptr
unsignedlong*p

for(ptr=(unsignedlong)sys_close
ptr<(unsignedlong)&loops_per_jiffy
ptr+=sizeof(void*)){

p=(unsignedlong*)ptr

if(p[__NR_close]==(unsignedlong)sys_close){
printk(KERN_DEBUG"Foundthesys_call_table!!!\n")
return(unsignedlong**)p
}
}

returnNULL
}

Whatwearedoinghereislookingforthepointertothesys_call_tablesymbol.Withthistableinhandswecanoverwriteitsentriestohavedifferentfunctions
calledinplaceoftheexpectedsyscall.
Theforloopstartslookingattheaddressofthefunctionsys_closeandrunsuptotheaddressofthesymbolloops_per_jiffytryingtofindthesys_call_tablesymbol.
IhavesetthesetwoasstartandendpointsbasedonmySystem.map(locatedon/boot/)filewhichhastheseentries:
ffffffff81175dc0Tsys_close
ffffffff81801300Rsys_call_table
ffffffff81c0f3a0Dloops_per_jiffy

Aswecanseetheaddressofthesys_call_tableisbetweensys_closeandloops_per_jiffy.Ibelievethismightbetrueformostkernelsinthe3.xline,thatisthe
reasonwhyIhaveselectedtheseaddressesasthespacetolookforthesys_call_table.
TheletterRbeforethesys_call_tablemeansthatthismemoryregionisreadonlysowewillnotbeabletosimplygettheaddresstothesyscalltableanddirectly
modifyit.
staticint__initsyscall_init(void)
{
intret
unsignedlongaddr
unsignedlongcr0

syscall_table=(void**)find_sys_call_table()

...

cr0=read_cr0()
write_cr0(cr0&~CR0_WP)

addr=(unsignedlong)syscall_table

...

orig_sys_open=syscall_table[__NR_open]
syscall_table[__NR_open]=my_sys_open

write_cr0(cr0)

return0
}

http://www.gilgalab.com.br/hacking/programming/linux/2013/01/11/Hooking-Linux-3-syscalls/

2/3

10/16/2016

Hooking Linux 3 Syscalls

Asthesys_call_tableisreadonlyweneedtomakeitwriteable.Inordertodothat,weneedtomakesurethattheWriteProtectbitincr0isdisabled.Theregister
cr0isacontrolregisterintheIntelarchitecturethatcontainsaflagcalledWPonbit16(bitcountstartsat0)whenthisflagissetto1anymemorypagethatisset
readonlycannotbechangedtobewritable,soweneedtochangethisflagbackto0beforewecancallset_memory_rwtomakethesys_call_tablewritable
again.NotethatattheendofthefunctionIsetthecr0registerbacktoitsoriginalvalueasagoodmeasure,meaningthatthesyscalltablecannotbechanged
again.
Atthispoint,wesimplychangethesys_call_tableindexwewanttopointtoafunctionofoursthathasTHESAMEprototypeastheoriginalsyscallinthisindex.
NotethatIamkeepingtheaddressoftheoriginalsycallsaved,aswewillprobablywanttocallitinsideournewfunctionandaswewillneedtosetitbackinside
thetablewhenweremovethismodule.
Foralistoftheprototypesofeachsyscall,havealookintothefileinclude/linux/syscalls.hinthesourceofthelinuxkernel.Thelistofsyscallindexes(foxx64)can
befoundinthefile/usr/include/x86_64linuxgnu/asm/unistd_64.honmysystem.
Afterallthisisdonewejustneedtomakesurethatwhenourmoduleisremovedwesetbackthecorrectaddressfortheoverwrittenentryinthesys_call_table.
staticvoid__exitsyscall_release(void)
{
unsignedlongcr0

/*Makethesys_call_tablewritableagain*/
cr0=read_cr0()
write_cr0(cr0&~CR0_WP)

/*Restoretheoldpointer*/
syscall_table[__NR_open]=orig_sys_open

/*Bringcr0backtowhatitwas*/
write_cr0(cr0)
}

Thisisthefirststepintobuidlingarootkitorasyscallproxy.Sohavefunanddonotabusetheknowledge:P
ThecodewiththemakefilecanbefoundatmyGitHub

References
http://www.gadgetweb.de/linux/40howtohijackingthesyscalltableonlatest26xkernelsystems.html
http://kerneltrap.org/mailarchive/linuxkernel/2008/1/25/612014
http://badishi.com/kernelwritingtoreadonlymemory/

Previous

Archive

Next

HenriqueM.D.2012withhelpfromJekyllBootstrapandTwitterBootstrap

http://www.gilgalab.com.br/hacking/programming/linux/2013/01/11/Hooking-Linux-3-syscalls/

3/3

Vous aimerez peut-être aussi