Created
March 26, 2011 08:03
-
-
Save rednaxelafx/888122 to your computer and use it in GitHub Desktop.
Hack HotSpot's interpreter with return stack shellcode. Requires JRuby and BiteScript to build, works on WinXP 32-bit only. If run under a SecurityManager then it'll be caught and a security exception will be thrown before it wrecks havoc; it's configured
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
D:\sdk\jruby-1.4.0\bin>java -version | |
java version "1.6.0_23" | |
Java(TM) SE Runtime Environment (build 1.6.0_23-b05) | |
Java HotSpot(TM) Client VM (build 19.0-b09, mixed mode, sharing) | |
D:\sdk\jruby-1.4.0\bin>jruby test_native_invoke.rb | |
D:\sdk\jruby-1.4.0\bin>javac TestStackOpsMain.java | |
D:\sdk\jruby-1.4.0\bin>java -Xint TestStackOpsMain | |
Greetings from generated code! | |
Greetings from managed code! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
D:\sdk\jruby-1.4.0\bin>jruby test_stack_ops.rb | |
D:\sdk\jruby-1.4.0\bin>\sdk\groovy-1.7.2\bin\groovysh | |
Groovy Shell (1.7.2, JVM: 1.6.0_23) | |
Type 'help' or '\h' for help. | |
------------------------------------------------------------------------------- | |
groovy:000> Integer.toString(TestStackOps.getParam0(0x12345678), 16) | |
===> 12345678 | |
groovy:000> Integer.toString(TestStackOps.getParam0(0x76543210), 16) | |
===> 76543210 | |
groovy:000> Integer.toString(TestStackOps.getReturnAddress(), 16) | |
===> 972f45 | |
groovy:000> Integer.toString(TestStackOps.getReturnAddress(), 16) | |
===> 972f45 | |
groovy:000> TestStackOps.gotoSegv() | |
# | |
# A fatal error has been detected by the Java Runtime Environment: | |
# | |
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00000042, pid=2984, tid=5652 | |
# | |
# JRE version: 6.0_23-b05 | |
# Java VM: Java HotSpot(TM) Client VM (19.0-b09 mixed mode, sharing windows-x86 | |
) | |
# Problematic frame: | |
# C 0x00000042 | |
# | |
# An error report file with more information is saved as: | |
# D:\sdk\jruby-1.4.0\bin\hs_err_pid2984.log | |
# | |
# If you would like to submit a bug report, please visit: | |
# http://java.sun.com/webapps/bugreport/crash.jsp | |
# |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
D:\sdk\jruby-1.4.0\bin>java -version | |
java version "1.6.0_23" | |
Java(TM) SE Runtime Environment (build 1.6.0_23-b05) | |
Java HotSpot(TM) Client VM (build 19.0-b09, mixed mode, sharing) | |
D:\sdk\jruby-1.4.0\bin>jruby test_native_invoke.rb | |
D:\sdk\jruby-1.4.0\bin>javac TestStackOpsMain.java | |
D:\sdk\jruby-1.4.0\bin>java -Xint TestStackOpsMain | |
Greetings from generated code! | |
Greetings from managed code! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'rubygems' | |
require 'bitescript' | |
include BiteScript | |
MagicAccessorImpl = Java::SunReflect::MagicAccessorImpl | |
BiteScript.bytecode_version = JAVA1_6 | |
builder = FileBuilder.build(__FILE__) do | |
public_class 'NativeCode', MagicAccessorImpl do | |
public_static_method :invokeVoid, [], void, byte[] do | |
iinc 0, 4 * 3 # adjust the pointer to the contents of the code array | |
9.times { pop } # let esp point to the stack slot that holds the return address | |
swap # | |
returnvoid # make the jump to the code | |
end | |
end | |
end | |
builder.generate do |filename, class_builder| | |
File.open(filename, 'wb') do |file| | |
file.write(class_builder.generate) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'rubygems' | |
require 'bitescript' | |
include BiteScript | |
MagicAccessorImpl = Java::SunReflect::MagicAccessorImpl | |
BiteScript.bytecode_version = JAVA1_6 | |
builder = FileBuilder.build(__FILE__) do | |
public_class 'TestStackOps', MagicAccessorImpl do | |
public_static_method :getParam0, [], int, int do | |
10.times { pop } # let esp point to the stack slot that holds parameter 0 | |
ireturn # parameter 0 now looks like the top-of-stack slot, so it gets returned | |
end | |
public_static_method :getReturnAddress, [], int do | |
9.times { pop } # let esp point to the stack slot that holds the return address | |
ireturn | |
end | |
public_static_method :gotoSegv, [], void do | |
9.times { pop } # let esp point to the stack slot that holds the return address | |
istore 0 # save the return address somewhere for later use (if any) | |
push_int 0x42 # overwrite the return address | |
returnvoid # make a jump to 0x00000042, causing a segfault | |
end | |
end | |
end | |
builder.generate do |filename, class_builder| | |
File.open(filename, 'wb') do |file| | |
file.write(class_builder.generate) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class TestStackOpsMain { | |
public static void main(String[] args) { | |
// refer to earlier blog post, http://rednaxelafx.javaeye.com/blog/461787 | |
byte[] code = { | |
// CODE SECTION | |
// push ebp | |
0x55, | |
// mov ebp,esp | |
(byte) 0x8B, (byte) 0xEC, | |
// push -0B ; /DevType = STD_OUTPUT_HANDLE | |
0x6A, (byte) 0xF5, | |
// mov eax,KERNEL32.GetStdHandle ; | | |
(byte) 0xB8, (byte) 0xD9, 0x2F, (byte) 0x81, 0x7C, | |
// call eax ; \GetStdHandle | |
(byte) 0xFF, (byte) 0xD0, | |
// push 0 ; /pReserved = NULL | |
0x6A, 0x00, | |
// push 0 ; |pWritten = NULL | |
0x6A, 0x00, | |
// push 1F ; |CharsToWrite = 1F (31.) | |
0x6A, 0x1F, | |
// call <&next_instruction> ; | | |
(byte) 0xE8, 0x00, 0x00, 0x00, 0x00, | |
// add dword ptr ss:[esp],10 ; |Buffer | |
(byte) 0x83, 0x04, 0x24, 0x10, | |
// push eax ; |hConsole | |
0x50, | |
// mov edx,KERNEL32.WriteConsoleA ; | | |
(byte) 0xBA, 0x5D, (byte) 0xCC, (byte) 0x81, (byte) 0x7C, | |
// call edx ; \WriteConsoleA | |
(byte) 0xFF, (byte) 0xD2, | |
// mov esp,ebp | |
(byte) 0x8B, (byte) 0xE5, | |
// pop ebp | |
0x5D, | |
// ret | |
(byte) 0xC3, | |
// DATA SECTION | |
// null-terminated string "Greetings from generated code!" | |
0x47, 0x72, 0x65, 0x65, 0x74, 0x69, 0x6E, 0x67, 0x73, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x67, 0x65, 0x6E, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x20, 0x63, 0x6F, 0x64, 0x65, 0x21, 0x0A, 0x00 | |
}; | |
NativeCode.invokeVoid(code); // "Greetings from generated code!" | |
System.out.println("Greetings from managed code!"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment