sábado, 24 de abril de 2010

Ensamblador inline en código C

Para incluir código ensamblador en un programa escrito en C la sintaxis es la siguiente.

#include <stdio.h>

int main(){
int var1 = 1;
int var2;
int var3;

__asm__(
"inc %%eax \n\t"
"movl %%eax, %%ecx \n\t"
"inc %%ecx \n\t"
:"=a" (var2), "=c" (var3)
:"a" (var1)
);

printf("Value1: %d\n", var1);
printf("Value2: %d\n", var2);
printf("Value3: %d\n", var3);


return 0;
}

Los paréntesis se escriben dobles para escapar el carácter '%' ya que en C es un modificador de cadena.

Todas las líneas acaban en '\n\t' para que el código en ensamblador quede formateado igual que el resto.

Los registros no se usan con el nombre como tal para las entrada/salida, se usan alias del tipo "a=eax, b=ebx, c=ecx...".

En el primer apartado "=a" (var2), "=c" (var3) se les está diciendo que el contenido final de eax lo lleve a var2 y el contenido de ecx lo lleve a var3.

En el segundo apartado "a" (var1) se le dice que se comience el bloque copiando el valor de var1 a eax, actuará como entrada.

El compilador da por hecho que los registros usados para entrada/salida del bloque en ensamblador no los puede reutilizar, pero si se utilizan más registros se pueden poner en un tercer apartado de forma opcional.

El bloque ensamblador escrito antes, hará lo siguiente:

1. Copia el valor de var1 a eax.
2. Incrementa el valor de eax en 1.
3. Copia el contenido de eax a ecx.
4. Aumenta el valor de ecx en 1.
5. Copia el valor de eax a var2.
6. Copia el valor de ecx a var3.

martes, 20 de abril de 2010

Position Independent Code

El position independent code o código no dependiente de posición es aquel que se puede reubicar en memoria y aún así seguirá funcionando correctamente.

Por defecto, en Mac el código producido por gcc es PIC, pero se puede forzar a que produzca código no PIC con la opción -fno-pic.
Si tomamos por ejemplo el siguiente código en C.

#include<stdio.h>

void func(){
printf("Hello again\n");
}

int main(){
printf("Hello world\n");
func();

return 0;
}

Y lo compilamos como no PIC con la siguiente instrucción.

gcc -fno-pic -S program.c -o nopic.asm

Se obtiene.

.cstring
LC0:
.ascii "Hello again\0"
.text
.globl _func
_func:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
movl $LC0, (%esp)
call _puts
leave
ret
.cstring
LC1:
.ascii "Hello world\0"
.text
.globl _main
_main:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
movl $LC1, (%esp)
call _puts
call _func
movl $0, %eax
leave
ret
.subsections_via_symbols

Se puede ver que la cadena almacenada en la línea 3 se referencia en la línea 10 de forma absoluta. Si cambia la ubicación del programa en memoria LC0 seguirá referenciando a la misma posición, pero allí ya no estará la cadena que se esperaba.

Por el contrario, si dejamos al compilador con las opciones por defecto, producirá código PIC, quedando de la siguiente forma.


.cstring
LC0:
.ascii "Hello again\0"
.text
.globl _func
_func:
pushl %ebp
movl %esp, %ebp
pushl %ebx
subl $20, %esp
call L3
"L00000000001$pb":
L3:
popl %ebx
leal LC0-"L00000000001$pb"(%ebx), %eax
movl %eax, (%esp)
call L_puts$stub
addl $20, %esp
popl %ebx
leave
ret
.cstring
LC1:
.ascii "Hello world\0"
.text
.globl _main
_main:
pushl %ebp
movl %esp, %ebp
pushl %ebx
subl $20, %esp
call L6
"L00000000002$pb":
L6:
popl %ebx
leal LC1-"L00000000002$pb"(%ebx), %eax
movl %eax, (%esp)
call L_puts$stub
call _func
movl $0, %eax
addl $20, %esp
popl %ebx
leave
ret
.section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5
L_puts$stub:
.indirect_symbol _puts
hlt ; hlt ; hlt ; hlt ; hlt
.subsections_via_symbols

En esta ocasión se puede ver que en la línea 15 se carga la cadena, pero de forma relativa, usando la diferencia entre la posición actual y la de la cadena. Además, se puede ver que hay unas nuevas directivas al incluir la función puts.

¿Por qué puede preferirse la generación de código no PIC? Pues observando los ejemplos se puede ver que generar código no dependiente de la posición del programa requiere más instrucciones en ensamblador y por tanto mayor tiempo a la hora de ejecutarse.

lunes, 19 de abril de 2010

Paso de mensajes entre procesos en windows

En la plataforma Windows tanto para la comunicación entre procesos como para el manejo de eventos se usa un sistema de mensajes.

Una de las características del sistema de mensajes de Windows es no disponer de autentificación, se puede aprovechar este hecho para simular eventos en los programas que se están ejecutando y de esta forma controlarlos desde el API de mensajes.

Se puede por tanto manejar un programa de forma automática desde otro, con las posibilidades que ello ofrece. Orientándolo a la ingeniería inversa se puede hacer fuzzing a programas que tan solo admiten entradas desde la interfaz gráfica.

Supongamos que tenemos un programa cuya ventana principal se llama "Form1" y un botón con el texto "Boton" en el cual al hacer click en un botón muestra un mensaje.

...
private void button_Click(object sender, EventArgs e){
MessageBox.Show("Wow!", "Clicked", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
...

Podemos simular que hacemos click en ese botón si desde otro programa hacemos lo siguiente.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WFuzzing{
public partial class Form2 : Form{
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr FindWindow(string strClassName, string strWindowName);

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int SendMessage(int hWnd, uint Msg, long wParam, long lParam);

[DllImport("user32.dll", CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam);
public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr parameter);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);

public const int WM_LBUTTONDOWN = 0x0201;
public const int WM_LBUTTONUP = 0x0202;

public Form2(){
InitializeComponent();
}

private void fuzzbutton_Click(object sender, EventArgs e){
IntPtr wHandle = FindWindow(null, "Form1");
List<IntPtr> result = new List<IntPtr>();
GCHandle listHandle = GCHandle.Alloc(result);
EnumWindowsProc childProc = new EnumWindowsProc(EnumWindow);
EnumChildWindows(wHandle, childProc, GCHandle.ToIntPtr(listHandle));
}

private static bool EnumWindow(IntPtr handle, IntPtr pointer){
StringBuilder text = new StringBuilder(256); ;
GetWindowText(handle, text, text.Capacity);

if(text.ToString() == "Boton"){
long lngResult = SendMessage(handle.ToInt32(), WM_LBUTTONDOWN, 0, 0);
long lngResult2 = SendMessage(handle.ToInt32(), WM_LBUTTONUP, 0, 0);
}
return true;
}

}
}

Se le mandan dos mensajes, el primero el de hacer click con el ratón y el segúndo el de levantar el dedo del ratón.

Al ejecutar ese código el primer programa debería mostrar el mismo mensaje que si hacemos click en el botón.

De forma similar, se puede automatizar la búsqueda de fallos en programas de los cuales no disponemos del código fuente, tan solo manipulando la interfaz, rellenando campos de texto, activando y desactivando controles, todo de forma automática.

miércoles, 7 de abril de 2010

Metaprogramación en c#

Aunque c# no proporcione demasiadas ayudas sintácticas a la metaprogramación si que se pueden aprovechar sus estructuras y tipos de datos para generar métodos de fórma dinámica.

En el siguiente código hay un ejemplo.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Collections;
using System.Runtime.InteropServices;


namespace example1{
class Program{
[DllImport("msvcrt.dll")]
static extern bool system(string str);

static void Main(string[] args){
Dictionary<string, Action<string>> method = new Dictionary<string, Action<string>>();
Expression<Action<string>> exp;

for (int i = 0; i < 100; i++)
{
var number = i;
exp = (p => Console.WriteLine("Parametro: " +p+"\nMetodo numero: "+number));
method["print_" + i] = exp.Compile();

exp = (p => Console.WriteLine(p + number));
method["concat_" + i] = exp.Compile();
}

method["print_17"]("test");
method["concat_35"]("Concatenando el numero -> ");


system("pause");
}
}
}

En primer lugar se crea un diccionario llamado method para contener todas las funciones generadas automáticamente.

Luego, en el bucle se crean 200 métodos, tanto dependientes de parámetro como de su posición en el bucle, sin embargo, para esto es necesario un pequeño hack.
Se le asigna a number el valor del contador, creando un objeto en cada iteración, en caso contrario todos los métodos creados tendrán como valor de i el último que ha tomado en el bucle, es decir, 100.

martes, 6 de abril de 2010

Expresiones regular en C++ con boost

La mayoría lenguajes de programación modernos proporcionan la posibilidad de usar expresiones regulares de forma nativa desde el propio lenguaje, sin embargo, en C++ es necesario recurrir a alguna librería como Boost.Regex.

Boost.Regex ofrece la mayoría de funciones comunes de las expresiones regulares.

#include <iostream>
#include <string>
#include <boost/regex.hpp>

int main(){
std::string s = "BEGIN->Cadena_entre_delimitadores<-END";
std::string s2 = "Cadena de texto con 3 numeros para sustituir 1, 4 por incognitas";
boost::regex r("BEGIN->(\\w+)<-END");
boost::regex r2("\\d");
boost::smatch result;

if (boost::regex_search(s, result, r)){
for(int i=0; i<result.size(); i++){
std::cout << "Ocurrencia n " << i+1 << ": "<< result[i] << std::endl;
}
}
else{
std::cout << "Ninguna coincidencia" << std::endl;
}

std::cout << "---" << std::endl;
std::string number("X");
std::cout << "Cadena modificada con una expresion regular: ";
std::cout << boost::regex_replace(s2, r2, number) << std::endl;

}

Con regex_search se pueden encontrar coincidencias de una expresión regular r dentro de una cadena s. Como resultado también tendrá en cuenta los grupos de captura.

Con regex_replace se pueden hacer sustituciones, cambiando las ocurrencias encontradas en la cadena s2 según el patrón r2, sustituyéndolas por number.

Papra compilar es necesario incluir tanto los headers como la librería correspondiente, en mi caso.

g++ -lboost_regex-mt -I/opt/local/include/ -L/opt/local/lib/ regex.cpp -o regex