You can write push '/bin'
in NASM to get the bytes into memory in that order. (Padded with 4 bytes of zeros, for a total width of qword; dword pushes are impossible in 64-bit mode.) No need to mess around with manually encoding ASCII characters; unlike some assemblers NASM doesn't suck at multi-character literals and can make your life easier.
You could use use mov dword [rsp+4], '//ls'
to store the high half. (Or make it a qword
store to write another 4 bytes of zeroes past that, with a mov r/m64, sign_extended_imm32
.) Or just zero-terminate it with an earlier push before doing mov rsi, '/bin//ls'
/ push rsi
if you want to store exactly 8 bytes.
Or mov eax, '//ls'
; shr eax, 8
to get EAX="/ls\0"
in a register ready to store to make an 8-byte 0-terminated string.
Or use the same trick of shifting out a byte after mov r64, imm64
(like in @prl's answer) instead of separate push / mov. Or NOT your literal data so you do mov rax, imm64
/ not rax
/ push rax
, producing zeros in your register without zeros in the machine code. For example:
mov rsi, ~`/bin/ls\0` ; mov rsi, 0xff8c93d091969dd0
not rsi
push rsi ; RSP points to "/bin/ls", 0
If you want to leave the trailing byte implicit, instead of an explicit \0
, you can write mov rsi, ~'/bin/ls'
which assembles to the same mov rsi, 0xff8c93d091969dd0
. Backticks in NASM syntax process C-style escape sequences, unlike single or double quotes. I'd recommend using \0
to remind yourself why you're going to the trouble of using this NOT, and the ~
bitwise-negation assemble-time operator. (In NASM, multi-character literals work as integer constants.)
I believe that to set up the first one, it suffices doing
push 0x736c2f2f ;sl//
push 0x6e69622f ;nib/
mov rdi, rsp
No, push 0x736c2f2f
is an 8-byte push, of that value sign-extended to 64-bit. So you've pushed '/bin\0\0\0\0//ls\0\0\0\0'
.
Probably you copied that from 32-bit code where push 0x736c2f2f
is a 4-byte push, but 64-bit code is different.
x86-64 can't encode a 4-byte push
, only 2 or 8 byte operand-size. The standard technique is to push 8 bytes at a time:
mov rdi, '/bin//ls' ; 10-byte mov r64, imm64
push rdi
mov rdi, rsp
If you have an odd number of 4-byte chunks, the first one can be push imm32
, then use 8-byte pairs. If it's not a multiple of 4, and you can't pad with redundant characters like /
, mov dword [mem], imm32
that partially overlaps might help, or put a value in a register and shift to introduce a zero byte.
See