Monday, December 29, 2003

I was studying the C# language one day and thought back to earlier in my career. Back then I was learning the assembly language for a little 8 bit Hitachi CPU (the 6303) in order to control a small thermal printer. With the right control codes you could get the printer to display a custom message on the LCD. Then I was walking by the HP Laser printer in the office and wondered if I could do the same here. Once I uncovered the Printer Job Language Reference from HP, I realized this could be fun. After all, who would not get a kick out of a printer with the message “TOUCH ME” on the LCD?

So I wrote some C# and had everything working. I put a list of messages together for the program to display at random and setup a scheduled task to execute the assembly every hour. It didn’t take long for people to notice and start commenting. Some people would check the printer for a new message on every trip. I remained completely silent as to my knowledge of the origin of these messages.

At one point I disabled my scheduled task because our chief network admin had made it his mission to stop the printer hacking. After locking down everything on the printer he possibly could, the messages still got through, but I figured the joke had run it’s course. Then, when everyone realized we were going out of business, I turned it back on for a little bit of amusement everyday.

After the company was sold and I did some consulting for the buyer, I setup the program in their office too. I had it hit an HP printer nearest the engineering cubicles, where at least one guy I know slept behind his high cubicle walls every afternoon for an hour. It never raised many eyebrows that I know of while I was there, but afterwards someone told me they knew one lady who stopped at the printer every day “because it says such nice things to me”. If I can brighten one person's day, every day, my mission is accomplished.

The following listing is the code to pull it off. I think the selection of random messages is quite funny to see on a printer, but feel free to modify these to match your own sense of humor. To use the program just add the IP address of the printer and a message in quotes, or type "random" for the message to select from the random message list.

namespace hphack { using System; using System.Text; using System.Net; using System.Net.Sockets; public class PrnHack { public static int Main(string[] args) { if(!ParseArgs(args)) { return -1; } Console.WriteLine("

HP Display Hack"); Console.WriteLine("Host: {0}", args[0]); Console.WriteLine("Message: {0}

", message); IPEndPoint ipEndPoint; ipEndPoint = new IPEndPoint( Dns.Resolve(args[0]).AddressList[0], PJL_PORT); Console.WriteLine("Host is {0}", ipEndPoint.ToString()); Socket socket; socket = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp ); socket.Connect(ipEndPoint); byte [] sendData; string sendString; sendString = String.Format( "\x1B%-12345X@PJL RDYMSG DISPLAY = \"{0}\"\r

\x1B%-12345X\r

", message ); sendData = Encoding.ASCII.GetBytes(sendString); int result; result = socket.Send(sendData, sendData.Length, 0); if(result == 0) { Console.WriteLine("Could not send on socket"); } socket.Close(); Console.WriteLine("Finished



"); return 0; } protected static bool ParseArgs(string[] args) { if(args.Length != 2) { Console.WriteLine( "HP Display Hack: " + "hphack printername \"message\" " ); return false; } if(args[1].Length > 16) { Console.WriteLine("Message must be <= 16 characters"); return false; } if(args[1].CompareTo("random") == 0) { message = GetRandomMessage(); } else { message = args[1]; } return true; } public static string GetRandomMessage() { string [] Messages = { "BUZZ OFF", "TOUCH ME", "STEP AWAY", "SET TO STUN", "SCORE = 3413", "PAT EATS MICE", "FEED ME", "GO AWAY", "NEED MORE SPACE", "POUR ME A DRINK", "IN DISTRESS", "NICE SHIRT", "GO AWAY", "NO PRINT FOR YOU", "RADIATION LEAK", "HANDS UP", "PRESS MY BUTTON", "TAKE ME HOME", "LOOKS LIKE RAIN", "HELLO WORLD", "NICE HAIR", "NEED A MINT?", "BE GENTLE", "BE KIND", "INSERT DISK", "BUY ME LUNCH", "DONT STOP", "COME CLOSER", "TAKE A BREAK", "INSERT QUARTER", "BLACK SABBATH" }; Random r = new Random(); return Messages[r.Next() % Messages.Length]; } protected const int PJL_PORT = 9100; protected static string message = "NO MESSAGE"; } }