Flying to the Moon

No, we are not going to talk about space travelling, or interplanetary missions. No. We are going to talk about Lua. Lua is Portuguese for Moon and it is a very nice scripting language that is usually hidden behind the Python hype.

Anyway, why are we talking about Lua?. Well, I have been planning to write a series of articles about “How does the hacker’s tools work?”, as a response to all those “How does you use those hacker’s tools without having a clue of what you are doing?”. I started talking about ProxyChains some weeks ago and this is the second post of the series.

Again. Why Lua?. Ok, two of the most widely used hacker’s tools are wireshark and nmap… And know what?.. both use Lua as scripting language. You can write wireshark dissectors, or sophisticated recon scripts using NSE (the Nmap Scripting Engine) and for doing both things you will have to write some Lua code.

Not a Language Tutorial

If you were expecting a Lua tutorial, I regret to disappoint you. There are very good tutorials on-line, and , on top of that, the language is pretty simple.

So, we are going to see how to add Lua scripting capabilities to our own tools… the same way that wireshark or nmap does.

Embedding a Scripting Language

When you embedded a scripting language in your applications, there are always two thing you have to do:

  • Load and run scripting code from external files
  • Allow the scripting code call functions provided by your application

These two things are what we are going to elaborate through this post.

I will be using Lua 5.1 in the examples. I haven’t tried neither 5.0 nor 5.2. Probably any of them will be OK but I cannot assure that.

Embedding a Lua Interpreter

Let’s start embedding a Lua interpreter in a C application and run an external Lua script. As you will shortly find out this is really simple:

#include <lua5.1/lauxlib.h>

static lua_State *l;

int
main(int argc, char *argv[])
{
  l = luaL_newstate ();
  luaL_openlibs (l);

  luaL_dofile (l, argv[1]);
  return 0;
}

The luaL_newstate initiates a new Lua environment. The lua_State var is, somehow, the handler for our Lua interpreter. Once the interpreter is started we need to load a minimal set of libraries. You have to do this if you want to print something on the console, open a file, do some math or manipulate strings. So, you better call luaL_openlibs just before you initialise your Lua environment.

Now, it is time to compile it:

gcc -o test1 test1.c `pkg-config --cflags --libs lua5.1`

To test this first program, we need a Lua script. So let’s write the omnipresent Hello World in Lua:

print ("Hello World")

Let’s save it in a file named hello.lua

Now we can run our application:

$ ./test1 hello.lua
Hello World

So far so good.

A Stack Machine

Before going further in our trip to the moon, we have to introduce the concept of stack machine. A stack machine is a kind of computer that uses a stack for its operations instead of registers as most of the processors you may know. Check the wiki for details https://en.wikipedia.org/wiki/Stack_machine.

Lua has been build this way, and all operations and symbols used by a Lua instance have to go in and out of a virtual stack. So, from this point on, we will see how we push data into this stack to communicate with the Lua interpreter and how we pop data from the Lua interpreter to get results.

We will see in a bit all this at work, just be ready to see some pushs and pops in the code to interact with the interpreter.

Have you ever heard about Forth?. it is a stack-based language used by the Open Firmware project. So if you want to configure some non-x86 machine it will be handy to know a little bit of Forth

Getting the value of a variable

We have just learned how to run Lua scripts from our apps. Now we are going to see how to execute a specific function in a Lua script and how to get values out of that script. To do this test we need a more sophisticated Lua script. Please, welcome sum.lua

function sum (a,b)
	return a+b
end

r = sum (1,2)

This script defines a function that adds the two numbers it receives as a parameter, and then, in the main script body, it calls that function and stores the result in a global variable named r.

Let’s see how we can run the sum function from our app and how we can get the value of r.

#include <stdio.h>

#include <lua5.1/lauxlib.h>

static lua_State *l;

int
main(int argc, char *argv[])
{
  l = luaL_newstate ();
  luaL_openlibs (l);

  luaL_dofile (l, "sum.lua");

  /* Read Global var */
  lua_getglobal (l, "r");
  if (!lua_isnumber (l, -1)) return -1;
  printf ("Script calculation is: %d\n", (int)lua_tonumber(l, -1));
  lua_pop (l, 1);


  return 0;
}

The beginning of our program initialises the Lua context, as usual, and then it opens and executes the sum.lua file.

The next thing the program does is to get the value of r, the variable set in our Lua script. Any global symbol in the Lua environment can be accessed with the lua_getglobal function. This function will add to the Lua virtual stack the symbol passed as second parameter. In this case the global var r.

Then it checks if the result is actually a number. The lua_isnumber does this test. The second parameter is the index in the virtual stack. The stack pointer points to the next available position in the stack, so the value -1 references the last value pushed into the stack.

Now we know that we have a Lua number in the top of the stack. We have to convert it to a C number before being able to print it in our C program. This is common to most scripting languages out there. They manage their own internal types in order to provide all their magic (duck typing for instance) but, when those languages are embedded, a bit of conversion code is always needed. Anyway, lua_tonumber converts the object in the stack to a number.

Finally we have to clean the stack. We have used our global and we do not need it any more, so we can remove it from the stack using lua_pop. The second parameter here, indicates how many objects we want to pop from the stack.

Smart Configuration files

What we have discussed so far does not look very impressive, but, as suggested in the official Lua documentation, we had already set up the fundamentals for a smart configuration system for our applications.

Let’s write a very simple Lua script to configure our application

user = os.getenv("USER")

if user == "root" then
        home_dir = "/root"
else
        home_dir ="/home/"..user
end

So, this script sets two configuration parameters, a user name and a home folder name. User name is obtained from the current environment and the folder directory is dynamically determined based on the user name. This is the power of using a scripting language to write configuration files. you can run code to produce your configuration on the fly based on, for instance, the current environment.

For completeness, this is a small C program, using this configuration file:

#include <stdio.h>
#include <lua5.1/lauxlib.h>

static lua_State *l;

int
main(int argc, char *argv[])
{
  l = luaL_newstate ();
  luaL_openlibs (l);

  luaL_dofile (l, "config.lua");
  lua_getglobal (l, "home_dir");
  printf ("Configuration folder is:%s\n", (char*)lua_tostring(l,-1));

  lua_close (l);
  return 0;
}

You can define more complex data structures that may be more suitable for your current application… but that is a bit beyond of this already quite long post :). You should go and read the original Lua documentation for all the details and to get to know the tables, a powerful Lua data type.

Calling a function

At this point, we have introduce almost everything needed to call a function. Functions are also global objects (at least for our current knowledge of the environment). We already know how to get them in the stack (lua_getglobal), and we know how to also push data into the stack. This is how we are going to pass parameters.

The last missing part is how to tell Lua that we want it to call a function using all those values in the stack.

Let’s go back to our sum example and let’s do some small changes:

#include <stdio.h>

#include <lua5.1/lauxlib.h>

static lua_State *l;

int
main(int argc, char *argv[])
{
  l = luaL_newstate ();
  luaL_openlibs (l);

  luaL_dofile (l, "sum.lua");

  lua_getglobal (l, "sum");
  lua_pushnumber (l, 10);
  lua_pushnumber (l, 20);
  lua_pcall (l, 2, 1, 0);
  printf ("Result:%d\n", (int)lua_tonumber(l, -1));

  lua_pop (l, 1);
  lua_close (l);
  return 0;
}

The interface is pretty much the same that the one we used to access the global var, but now, using the lua_pcall function to actually execute the function. This is a summary of how it works:

  • Get the function using lua_getglobal
  • Push the parameters in the stack
  • Invoke the function using pcall. The second parameter is the number of parameters we are passing to the function. The third parameter is the number of values returned by the function. The forth parameter we will not discuss now.
  • The return value(s) will be pushed into the virtual stack, so we can get them, and convert to C types as required.
  • Finally we clean-up the stack removing the return value

This may look a bit cumbersome, but it can be easily improved using a vararg function. Check this link for a reference implementation: https://www.lua.org/pil/25.3.html

The last piece

The last piece to complete our Lua interface is to enable our Lua script to call C functions. Adding a C function to the current Lua environment is pretty simple:

lua_pushcfunction (l, c_func);
lua_setglobal (l, "c_func");

The code above will add a function named c_func (that we will define right away) to the Lua environment, and creates a global object named c_func that any lua script can actually execute. The C function will look like this:

int
c_func (lua_State *L)
{
   int x;
   if (lua_gettop(L) >= 0) {
     x = (int) lua_tonumber (L, -1);
     printf ("Received : %d\n", x);
     /* Returning x + 1*/
     lua_pushnumber(L, x + 1);
   }
   return 1;
}

It should look familiar at this point. The function will receive the current Lua environment as unique parameter. When calling the function from the Lua script, the parameters are automatically pushed into the Lua virtual stack before transferring control to the C function. In the same way, any return value (we can return more than one) have to be pushed into the stack before the C function returns.

So, this function, does the following:

  • Check that there is at least one value in the stack
  • Takes that value and converts it to a number (yes, you are right, we should check that it is actually a number… wonder how?)
  • Then we print the value so we can check the parameter made it to our C function
  • And finally we push the function return value that, in this case, is the function parameter increased by 1.

Now we can write Lua scripts like this (let’s call it c.lua):

x = 10
print (c_func(x))

That will output

$ ./test3 c.lua
Received : 10
11

Conclusions

This is the very basics to get a Lua interpreter integrated into your application, in the same way that wireshark or nmap does. Now, you are a step closer to write your own hacking tools… or any other tool that requires a scripting language ( https://en.wikipedia.org/wiki/Category:Lua-scripted_video_games )

Do you have an idea for a hacking tool using an scripting language?.. Let us know!

9 Likes

Damn! I knew that Lua was used in wireshark, but integrating it into C? Never thought of it that way. Awesome post @0x00pf!

1 Like

Great article! I honestly thought that Lua was used for scripting in video games. And at the end of the article you said [quote=“0x00pf, post:1, topic:593”]
Do you have an idea for a hacking tool using an scripting language?.. Let us know!
[/quote]
And just to add on I believe I do…

So how the tool would work is (and it would be scripted in Python for anyone wondering)- is that you would send a link to someone, and when they click on said link all they see is a picture similar to what you see when you press “view image” in Google Images.

Little do they know, perhaps that while viewing this seemingly harmless image. That it is in fact actually logging your IP.

And then you could add on attacking capabilities to the tool from there and so on.

Hope you like the idea! :smiley:

1 Like

What if I told you… this already exists, and is easier to do in PHP…

1 Like

Then you are a pico hater and you should be ashamed!

3 Likes

I see how this may be unclear, that was meant for Cromical.

1 Like

Awesome tutorial man ^^
I had been thinking about learning Lua for a while.
Also Ada, however I found out I don’t have to write missile guiding software, or Nuclear Power Plant driver modules, so I let that one slide.

Anyway I think this might be the perfect midway, between C and a scripting language.
It seems to work better than Cython, but that might just be because I hate Python.

Tons of ideas, after packet forging tutorial part 2.0,
I’ll write a DNS amplification script in Perl ^^

1 Like

Nice Tutorial man! I wonder though, is there any other languages we can extend with a different language? I mean, we have C extending Python, and now we have Lua extending C, so there has to be more right?

1 Like

I think i may have just fell in love with Lua… Time to play around a bit. My time long spent with python may start to suffer now :wink:

Great post!

2 Likes

Sounds interesting @Cromical . As @oaktree said, there are many different ways of doing something. I think all of them are valuable in a sense, at least, you will always learn something which is a good thing.

This Python idea looks interesting in the sense that you can build in one single program your webserver (a simple instantiation of SimpleHTTPServer module) and your scripting capabilities.

It would be nice if you make a post out of it!

Thanks @unh0lys0da. Glad to hear you liked.

I’m really looking forward to your packet forging articles… and going the Perl way is really cool!!!

Almost any single scripting language out there have this possibility. I have personally tried:

  • Python
  • Guile (the GNU scheme version)
  • Mono (it provides a pretty good interface)
  • Perl (maybe one of the trickiest)
  • Java (via JNI… a lot more verbose that all others)
  • tcl/tk (also very easy and a quick way to build a standard multiplatform GUI)
  • Lua (as you already know… this was actually the last I tried)

I haven’t yet played, at this level, with Rust or Go. Rust seems to be pretty straight forward. For Go, looks possible but, at first glance, looks like there are a bit less information available.

I know it is also possible with Ruby but I never tried myself.

I cannot recall more scripting languages right now :stuck_out_tongue:

This is awesome :slight_smile: I’ve always liked Lua.

1 Like

I very well know that. I made my own in PHP. However I think I could better implement it in Python as well as add on new features. Which was the entire gist of that part of my reply.

Ah thanks mate! I’ll keep the idea in mind!

This topic was automatically closed after 30 days. New replies are no longer allowed.