3

Wrote shellcode:

BITS 64
xor rax, rax
push rax
push dword "n/sh"
push dword "//bi"
mov rdi, rsp
push rax
mov rdx, rsp
push rdi
mov rsi, rsp
mov al, 59
syscall

When code execution reaches push instructions, strange things happen. The string /bin/sh must be sequentially written to the stack, but after the first instruction (and after the second) the values are equalized by 8-byte boundaries, which prevents the formation of a string, and I specified the DWORD

gdb:

=> 0x7fffffffea44:  push   0x68732f6e
   0x7fffffffea49:  push   0x69622f2f
   0x7fffffffea4e:  mov    rdi,rsp
   0x7fffffffea51:  push   rax
   0x7fffffffea52:  mov    rdx,rsp
   0x7fffffffea55:  push   rdi
   0x7fffffffea56:  mov    rsi,rsp
   0x7fffffffea59:  mov    al,0x3b
-----------------------------------------------------------------------------------------------------------------------------
0x00007fffffffea44 in ?? ()
gdb$ ni
Warning:
Cannot insert breakpoint 0.
Cannot access memory at address 0x68732f6e

-----------------------------------------------------------------------------------------------------------------------[regs]
  RAX: 0x0000000000000000  RBX: 0x0000000000000000  RBP: 0xFFFFFFFFFFFFFFFF  RSP: 0x00007FFFFFFFEA80  o d I t s Z a P c 
  RDI: 0x00007FFFFFFFEA40  RSI: 0x0000555555556021  RDX: 0x0000000000000079  RCX: 0x40FFFFFFFFFFFFFF  RIP: 0x00007FFFFFFFEA49
  R8 : 0x0000000000000000  R9 : 0x00007FFFF7FE14C0  R10: 0xFFFFFFFFFFFFF8F5  R11: 0x00007FFFF7E53B60  R12: 0x0000555555555060
  R13: 0x0000000000000000  R14: 0x0000000000000000  R15: 0x0000000000000000
  CS: 0033  DS: 0000  ES: 0000  FS: 0000  GS: 0000  SS: 002B                
-----------------------------------------------------------------------------------------------------------------------[code]
=> 0x7fffffffea49:  push   0x69622f2f
   0x7fffffffea4e:  mov    rdi,rsp
   0x7fffffffea51:  push   rax
   0x7fffffffea52:  mov    rdx,rsp
   0x7fffffffea55:  push   rdi
   0x7fffffffea56:  mov    rsi,rsp
   0x7fffffffea59:  mov    al,0x3b
   0x7fffffffea5b:  syscall 
-----------------------------------------------------------------------------------------------------------------------------
0x00007fffffffea49 in ?? ()
gdb$ ni
Warning:
Cannot insert breakpoint 0.
Cannot access memory at address 0x69622f2f

-----------------------------------------------------------------------------------------------------------------------[regs]
  RAX: 0x0000000000000000  RBX: 0x0000000000000000  RBP: 0xFFFFFFFFFFFFFFFF  RSP: 0x00007FFFFFFFEA78  o d I t s Z a P c 
  RDI: 0x00007FFFFFFFEA40  RSI: 0x0000555555556021  RDX: 0x0000000000000079  RCX: 0x40FFFFFFFFFFFFFF  RIP: 0x00007FFFFFFFEA4E
  R8 : 0x0000000000000000  R9 : 0x00007FFFF7FE14C0  R10: 0xFFFFFFFFFFFFF8F5  R11: 0x00007FFFF7E53B60  R12: 0x0000555555555060
  R13: 0x0000000000000000  R14: 0x0000000000000000  R15: 0x0000000000000000
  CS: 0033  DS: 0000  ES: 0000  FS: 0000  GS: 0000  SS: 002B                
-----------------------------------------------------------------------------------------------------------------------[code]
=> 0x7fffffffea4e:  mov    rdi,rsp
   0x7fffffffea51:  push   rax
   0x7fffffffea52:  mov    rdx,rsp
   0x7fffffffea55:  push   rdi
   0x7fffffffea56:  mov    rsi,rsp
   0x7fffffffea59:  mov    al,0x3b
   0x7fffffffea5b:  syscall 
   0x7fffffffea5d:  (bad)  
-----------------------------------------------------------------------------------------------------------------------------
0x00007fffffffea4e in ?? ()
gdb$ x/s $rsp
0x7fffffffea78: "//bi"
gdb$ x/16xb $rsp
0x7fffffffea78: 0x2f    0x2f    0x62    0x69    0x00    0x00    0x00    0x00
0x7fffffffea80: 0x6e    0x2f    0x73    0x68    0x00    0x00    0x00    0x00
gdb$ 

how can i solve this problem?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • 1
    `push` always pushes a `qword`. The `dword` keyword here specifies a `dword` sized immediate. This is to distinguish it from a `push byte` with a byte-sized immediate. In both cases, the immediate is zero-extended into a qword. – fuz Dec 12 '20 at 20:11
  • 2
    You can do `mov rax, '/bin//sh'` `push rax` Your DWORDS are being sign extended to make a 64-bit value. You can read about this behaviour in the Instruction Set Architecture reference for [PUSH](https://www.felixcloutier.com/x86/push) which says _"If the source operand is an immediate of size less than the operand size, a sign-extended value is pushed on the stack."_ . – Michael Petch Dec 12 '20 at 20:22
  • OK, thanks for answer. Why then can't I push 8 bytes onto the stack at once? What is the point of prohibiting this action if in any case everything is equalized to 8 bytes? – Станислав Тимошко Dec 12 '20 at 20:24
  • See my comment I show how you can push 8 bytes on the stack. There is no push 64-bit immediate in 64-bit code. You can move a 64-bit value to a 64-bit register and push that 64-bit register on the stack. – Michael Petch Dec 12 '20 at 20:25
  • 1
    Very few instructions in 64-bit mode have a 64-bit immediate operand. The only ones that do are the 64-bit register load instructions. – prl Dec 12 '20 at 20:26
  • Why can't I just ` push, "//bin/sh"`? – Станислав Тимошко Dec 12 '20 at 20:26
  • Because there is no push instruction that takes a 64-bit immediate value. It is a restriction of the Instruction set. If you review the link (ISA) in my earlier comment you can see all the rules for PUSH. You can move a 64-bit value to a register and push that register and I provided an example of that in the earlier comment as well. – Michael Petch Dec 12 '20 at 20:27
  • ok thanks for your answers! – Станислав Тимошко Dec 12 '20 at 20:29
  • [why we can't move a 64-bit immediate value to memory?](https://stackoverflow.com/q/62771323) explains some of the ISA-design reasons why this is a good and sensible design. See also [push on 64bit intel osx](https://stackoverflow.com/q/13351363) – Peter Cordes Dec 12 '20 at 21:20

0 Answers0