Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Gilgalab
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
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
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