rubypwn

pwntools for ruby developer

Getting Started

About rubypwn

A simple library for CTF pwning challegnges.

Like Python’s pwntools, it’s used to help you write exploit quickly.

Getting Started

Installation

gem install rubypwn

Basic Usage

class Exec

2.2.2 :002 > e = Exec.new "ls"
 => #<Exec:0x007f96742814e8>
2.2.2 :003 > e.gets
Makefile
 => "Makefile\n"
2.2.2 :004 > e = Exec.new "ls", debug: false, color: false
 => #<Exec:0x007f96742814e8>

class Netcat

2.2.2 :004 > e = Netcat.new "www.google.com", 80
 => #<Netcat:0x007f9671a00cf8>
2.2.2 :005 > e.puts "GET / HTTP/1.1"
GET / HTTP/1.1
 => #<IO:fd 12>
2.2.2 :006 > e.puts
 => #<IO:fd 12>
2.2.2 :008 > e.gets
HTTP/1.1 302 Found
 => "HTTP/1.1 302 Found\r\n"

Format String

Basic Usage

String Ext

2.2.3 :001 > require 'rubypwn'
 => true
2.2.3 :002 > str = "prefix_str_"
 => "prefix_str_"
2.2.3 :003 > str.fmtstr
str.fmtstr
2.2.3 :003 > str.fmtstr i32(0x601808), 10, bytes: 2
 => "prefix_str_%6152c%10$hn%59480c%11$hn"
2.2.3 :004 > str.fmtstr "system", 12, bytes: 2
 => "prefix_str_%6152c%10$hn%59480c%11$hn%30995c%12$hn%64256c%13$hn%63730c%14$hn"
2.2.3 :005 > "test".fmtstr i64(0x3121), 1, fmt_size: 100
 => "test%189c%1$hhn%16c%2$hhn%207c%3$hhn%4$hhn%5$hhn%6$hhn%7$hhn%8$hhn"

Module Index

All documented module in rubypwn.

Useful Function

  • def i64()

    2.2.2 :004 > a = 0x1234567890abcdef
     => 1311768467294899695
    2.2.2 :005 > i64 a
     => "\xEF\xCD\xAB\x90xV4\x12"
    
  • def i32()

  • def i16()

  • def s64()

  • def s32()

    2.2.2 :004 > a = "\x30\x00\x00\x00"
     => "0\u0000\u0000\u0000"
    2.2.2 :005 > s32 a
     => 48
    
  • def s16()

  • def c()

    2.2.2 :004 > a = 3
     => 3
    2.2.2 :005 > c a
     => "\x03"
    
  • def hex()

    2.2.2 :002 > a = "test"
     => "test"
    2.2.2 :003 > hex a
     => "74657374"
    
  • def nop()

    2.2.2 :002 > nop
     => "\x90"
    

class Asm

Used to compile assembly code

2.2.3 :004 > Asm.compile "push eax"
 => "50"
2.2.3 :005 > Asm.compile "push rax", arch: "amd64"
 => "50"
2.2.3 :012 > Asm.compile "mov r15, r14", arch: "arm", format: "c"
 => "\\x0e\\xf0\\xa0\\xe1"

class Elf

Used to get some constant value from the binary:

2.2.2 :001 > require 'pp'
2.2.2 :002 > require 'rubypwn'
 => true
2.2.2 :003 > e = Elf.new "traveller"
2.2.2 :004 > pp e
#<Elf:0x007fb498862550
 @arch="x86",
 @bits=32,
 @dynamic=
  {"strtab"=>134513496,
   "symtab"=>134513160,
   "rel_type"=>"REL",
   "jmprel"=>134513844},
 @global={"__gmon_start__"=>{"offset"=>134521192, "value"=>0}},
 @got=
  {"__errno_location"=>134521208,
   "sigemptyset"=>134521212,
   "getpid"=>134521216,
   "__gmon_start__"=>134521220,
   "__isoc99_sscanf"=>134521224,
   "fgets"=>134521228,
   "__libc_start_main"=>134521232,
   "sigaltstack"=>134521236,
   "siglongjmp"=>134521240,
   "sigaction"=>134521244,
   "strlen"=>134521248,
   "printf"=>134521252,
   "setvbuf"=>134521256,
   "puts"=>134521260,
   "kill"=>134521264,
   "__sigsetjmp"=>134521268,
   "exit"=>134521272},
 @sections=
  {""=>{"addr"=>0, "offset"=>0, "size"=>0, "flag"=>"r--"},
   ".interp"=>{"addr"=>134512948, "offset"=>308, "size"=>19, "flag"=>"r--"},
   ".note.ABI-tag"=>
    {"addr"=>134512968, "offset"=>328, "size"=>32, "flag"=>"r--"},
   ".hash"=>{"addr"=>134513000, "offset"=>360, "size"=>160, "flag"=>"r--"},
   ".dynsym"=>{"addr"=>134513160, "offset"=>520, "size"=>336, "flag"=>"r--"},
   ".dynstr"=>{"addr"=>134513496, "offset"=>856, "size"=>232, "flag"=>"r--"},
   ".gnu.version"=>
    {"addr"=>134513728, "offset"=>1088, "size"=>42, "flag"=>"r--"},
   ".gnu.version_r"=>
    {"addr"=>134513772, "offset"=>1132, "size"=>48, "flag"=>"r--"},
   ".rel.dyn"=>{"addr"=>134513820, "offset"=>1180, "size"=>24, "flag"=>"r--"},
   ".rel.plt"=>{"addr"=>134513844, "offset"=>1204, "size"=>136, "flag"=>"r--"},
   ".init"=>{"addr"=>134513980, "offset"=>1340, "size"=>48, "flag"=>"r-x"},
   ".plt"=>{"addr"=>134514028, "offset"=>1388, "size"=>288, "flag"=>"r-x"},
   ".text"=>{"addr"=>134514320, "offset"=>1680, "size"=>1612, "flag"=>"r-x"},
   ".fini"=>{"addr"=>134515932, "offset"=>3292, "size"=>28, "flag"=>"r-x"},
   ".rodata"=>{"addr"=>134515960, "offset"=>3320, "size"=>445, "flag"=>"r--"},
   ".eh_frame_hdr"=>
    {"addr"=>134516408, "offset"=>3768, "size"=>100, "flag"=>"r--"},
   ".eh_frame"=>
    {"addr"=>134516508, "offset"=>3868, "size"=>368, "flag"=>"r--"},
   ".ctors"=>{"addr"=>134520972, "offset"=>4236, "size"=>8, "flag"=>"rw-"},
   ".dtors"=>{"addr"=>134520980, "offset"=>4244, "size"=>8, "flag"=>"rw-"},
   ".jcr"=>{"addr"=>134520988, "offset"=>4252, "size"=>4, "flag"=>"rw-"},
   ".dynamic"=>{"addr"=>134520992, "offset"=>4256, "size"=>200, "flag"=>"rw-"},
   ".got"=>{"addr"=>134521192, "offset"=>4456, "size"=>4, "flag"=>"rw-"},
   ".got.plt"=>{"addr"=>134521196, "offset"=>4460, "size"=>80, "flag"=>"rw-"},
   ".data"=>{"addr"=>134521276, "offset"=>4540, "size"=>8, "flag"=>"rw-"},
   ".bss"=>{"addr"=>134521312, "offset"=>4548, "size"=>16812, "flag"=>"rw-"},
   ".comment"=>{"addr"=>0, "offset"=>4548, "size"=>61, "flag"=>"r--"},
   ".shstrtab"=>{"addr"=>0, "offset"=>4609, "size"=>213, "flag"=>"r--"}}>

Executable Index

All documented executable binary in rubypwn

patch_alarm

Patch alarm() to isnan().

How to use?

$ cat test.c && make test
#include <unistd.h>
main() {
    alarm(0);
}
cc     test.c   -o test

$ patch_alarm ./test
Done.

$ patch_alarm ./test.patch
No "alarm" found.

$ ltrace ./test.patch
__libc_start_main(0x40052d, 1, 0x7ffe3ca9a1b8, 0x400540 <unfinished ...>
isnan(0, 0x7ffe3ca9a1b8, 0x7ffe3ca9a1c8, 0)                                                      = 0
+++ exited (status 0) +++

Indices and tables