lib/pwnlib/shellcraft/generators/x86/linux/sleep.rb
# encoding: ASCII-8BIT
# frozen_string_literal: true
require 'pwnlib/shellcraft/generators/x86/common/pushstr'
require 'pwnlib/shellcraft/generators/x86/linux/linux'
require 'pwnlib/shellcraft/generators/x86/linux/syscall'
require 'pwnlib/util/packing'
module Pwnlib
module Shellcraft
module Generators
module X86
module Linux
# Sleep for a specified number of seconds.
#
# @param [Float] seconds
# The seconds to sleep.
#
# @example
# context.arch = :amd64
# puts shellcraft.sleep(1)
# # /* push "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" */
# # push 1
# # dec byte ptr [rsp]
# # push 1
# # /* call nanosleep("rsp", 0) */
# # push 0x23 /* (SYS_nanosleep) */
# # pop rax
# # mov rdi, rsp
# # xor esi, esi /* 0 */
# # syscall
# # add rsp, 16 /* recover rsp */
# #=> nil
#
# @note
# Syscall +nanosleep+ accepts a data pointer as argument, the stack will be used for putting the data
# needed. The generated assembly will use sizeof(struct timespec) = 16 bytes for putting data.
def sleep(seconds)
# pushes the data onto stack
tv_sec = seconds.to_i
tv_nsec = ((seconds - tv_sec) * 1e9).to_i
data = ::Pwnlib::Util::Packing.p64(tv_sec) + ::Pwnlib::Util::Packing.p64(tv_nsec)
cat Common.pushstr(data, append_null: false)
sp = ::Pwnlib::ABI::ABI.default.stack_pointer
cat Linux.syscall('SYS_nanosleep', sp, 0)
cat "add #{sp}, #{data.size} /* recover #{sp} */"
end
end
end
end
end
end