Showing posts with label source code. Show all posts
Showing posts with label source code. Show all posts

Sunday, October 4, 2015

Executing x86 machine code from char array in C/C++

The idea is:
  1. create bunch of char array in a file containing the machine code(not as const)
  2. mark the memory as executable with mprotect or VirtualProtect.
  3. declare typedef function with their correct parameters and pointing to the address of our char array
  4. call it
It's just pretty straightforward for a simple function, like a function that do x+1 or a*b, but function calling another function(e.x.: function calling strlen, malloc, etc.) needs the pointer to be calculated at first or the function will call wrong code(undefined berhaviour).

Okay so let's start. I've been make simple function that XOR 7303014 by x. This is the code


#include <stdio.h>
 
int foo_bar(int baz) {
 int foo=7303014;
 return foo^baz;
}
 
int main() {
 int val=1904132;
 int out=foo_bar(val);
 printf("%s",&out);
 return 0;
}


It looks simple right. It only prints string "bar" in the console. Now what we need is the foo_bar function as machine code. Open Hex Editor and open the executable then find the function.

Note: We are using x86 byte code for this. Take care of this if you're try to compile it as 64-bit code.
The highlighted hex is the foo_bar function that we need to get their machine code representation and put them in our new code. This is our char array declaration

char foo_bar[]={0x55, 0x89, 0xE5, 0x83, 0xEC, 0x10, 0xC7, 0x45, 0xFC, 0x66, 0x6F, 0x6F, 0x00, 0x8B, 0x45, 0x08, 0x8B, 0x55, 0xFC, 0x31, 0xD0, 0xC9, 0xC3};

Now we have completed point 1 above, now let's make some code to finish point 2, 3, and 4

typedef int (*foo_bar_t)(int );
 
int main() {
 foo_bar_t foo=(foo_bar_t)(void*)foo_bar;
 DWORD old_protect;
 VirtualProtect(foo,sizeof(foo_bar),PAGE_EXECUTE_READWRITE,&old_protect);
 int out=foo(0);
 printf("%s",&out);
 return 0;
}

Q: Why cast to void* first then cast it to foo_bar_t?
A: Visual Studio doesn't like casting foo_bar_t directly from char* so, cast it to void* first. GCC works fine without cast to void* above.

Ok that's our complete main function. Now let's explain it.

The point 2 is in the VirtualProtect function. VirtualProtect function mark address pointed by foo variable to be executable, readable, and writeable(see PAGE_EXECUTE_READWRITE). Without this call, point 4 will very likely to fail(throws Segmentation Fault/Access Violation)(be sure to include Windows.h)
The point 3 is above the main. The typedef.
Then, point 4 is below point 2. Again, calling the function without setting the memory protection would likely causes your program stop working.

Alright, this is the complete code


#include <stdio.h>
#include <windows.h>
 
typedef int (*foo_bar_t)(int );
 
char foo_bar[]={0x55, 0x89, 0xE5, 0x83, 0xEC, 0x10, 0xC7, 0x45, 0xFC, 0x66, 0x6F, 0x6F, 0x00, 0x8B, 0x45, 0x08, 0x8B, 0x55, 0xFC, 0x31, 0xD0, 0xC9, 0xC3};
 
int main() {
 foo_bar_t foo=(foo_bar_t)(void*)foo_bar;
 DWORD old_protect;
 VirtualProtect(foo,sizeof(foo_bar),PAGE_EXECUTE_READWRITE,&old_protect);
 int out=foo(0);
 printf("%s",&out);
 return 0;
}


Now let's compile it and run it.







Our program run without error. That means we've been successfully run our machine code. That's for today.

Challenge: Compile both complete code above and find out why it prints "bar" and "foo".

Monday, November 24, 2014

[C++|Windows 8]Get Accent & Background Color from Desktop Application

Windows 8 has some great features. Specially in the Metro design with some nice colors. This code will show how to get current used(selected) color in your start screen(personalization)


#include <windows.h>
#include <iostream>
 
typedef struct PersonalizationColor {
 int r;
 int g;
 int b;
} PersonalizationColor;
 
static const unsigned char ColorSet_Version3[25][2][3] = {    // Table for Accent & Background color in Windows 8
 {{37,37,37},{244,179,0}},
 {{37,37,37},{120,186,0}},
 {{37,37,37},{38,115,236}},
 {{37,37,37},{174,17,61}},
 {{46,23,0},{99,47,0}},
 {{78,0,0},{176,30,0}},
 {{78,0,56},{193,0,79}},
 {{45,0,78},{114,0,172}},
 {{31,0,104},{70,23,180}},
 {{0,30,78},{0,106,193}},
 {{0,77,96},{0,130,135}},
 {{0,74,0},{25,153,0}},
 {{21,153,42},{0,193,63}},
 {{229,108,25},{255,152,29}},
 {{184,27,27},{255,46,18}},
 {{184,27,108},{255,29,119}},
 {{105,27,184},{170,64,255}},
 {{27,88,184},{31,174,255}},
 {{86,156,227},{86,197,255}},
 {{0,170,170},{0,216,204}},
 {{131,186,31},{145,209,0}},
 {{211,157,9},{225,183,0}},
 {{224,100,183},{255,118,188}},
 {{105,105,105},{0,164,164}},
 {{105,105,105},{255,125,35}}
};
 
typedef struct windows_version {
 int major;    // CurrentVersion
 int minor;    // CurrentVersion
 int build_number;  // CurrentBuildNumber
 char name[256];   // ProductName
 char service_pack[256]; // CSDVersion(if exist)
 char edition[128];  // EditionID(if exist)
} windows_version;
 
int get_winver(windows_version* ptr) {
 HKEY temp;
 unsigned char CurrentVersion[8];
 long long long_temp=8;
 if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows NT\\CurrentVersion",0,KEY_READ,&temp)==ERROR_SUCCESS) {
  int a=0;
  if(RegQueryValueEx(temp,"CurrentVersion",0,nullptr,CurrentVersion,(LPDWORD)&long_temp)!=ERROR_SUCCESS)
   return 0;
  double current_version=strtod((char*)CurrentVersion,nullptr);
  ptr->major=(int)floor(current_version);
  ptr->minor=(int)floor(current_version*10.0)-ptr->major*10;
  long_temp=8;
  memset(CurrentVersion,0,8);
  if((a=RegQueryValueEx(temp,"CurrentBuildNumber",0,nullptr,CurrentVersion,(LPDWORD)&long_temp))!=ERROR_SUCCESS)
   return 0;
  ptr->build_number=atoi((char*)CurrentVersion);
  long_temp=256;
  if(RegQueryValueEx(temp,"ProductName",0,nullptr,(LPBYTE)ptr->name,(LPDWORD)&long_temp)!=ERROR_SUCCESS)
   return 0;
  int* from_lt=(int*)&long_temp+4;
  long_temp=256;
  *from_lt=RegQueryValueEx(temp,"CSDVersion",0,nullptr,(LPBYTE)ptr->service_pack,(LPDWORD)&long_temp);
  if(*from_lt==ERROR_FILE_NOT_FOUND)
   memset(ptr->service_pack,0,256);
  else if(*from_lt!=ERROR_SUCCESS)
   return 0;
  long_temp=128;
  *from_lt=RegQueryValueEx(temp,"EditionID",0,nullptr,(LPBYTE)ptr->edition,(LPDWORD)&long_temp);
  if(*from_lt==ERROR_FILE_NOT_FOUND)
   memset(ptr->edition,0,128);
  else if(*from_lt!=ERROR_SUCCESS)
   return 0;
 } else
  return 0;
 RegCloseKey(temp);
 return 1;
}
 
bool Win8GetAccentColor(PersonalizationColor* col) {
 windows_version win;
 get_winver(&win);
 if(win.major>=6 && (win.minor>=2 && win.minor<=3)) {
  HKEY temp;
  int r=0;
  if((r=RegOpenKeyExA(HKEY_CURRENT_USER,"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Accent",0,KEY_READ,&temp))==ERROR_SUCCESS) {
   auto accent_color=0UL;
   auto buf=4UL;
   if(win.minor==2) {
    if((r=RegQueryValueExA(temp,"ColorSet_Version3",nullptr,nullptr,(LPBYTE)&accent_color,&buf))==ERROR_SUCCESS) {
     col->r=ColorSet_Version3[accent_color][1][0];
     col->g=ColorSet_Version3[accent_color][1][1];
     col->b=ColorSet_Version3[accent_color][1][2];
     RegCloseKey(temp);
     return true;
    } else {
     RegCloseKey(temp);
     return false;
    }
   } else {
    if((r=RegQueryValueExA(temp,"AccentColor",nullptr,nullptr,(LPBYTE)&accent_color,&buf))==ERROR_SUCCESS) {
     col->r=GetRValue(accent_color);
     col->g=GetGValue(accent_color);
     col->b=GetBValue(accent_color);
     RegCloseKey(temp);
     return true;
    } else {
     RegCloseKey(temp);
     return false;
    }
   }
  } else
   return false;
 } else
  return false;
}
 
bool Win8GetBackgroundColor(PersonalizationColor* col) {
 windows_version win;
 get_winver(&win);
 if(win.major>=6 && (win.minor>=2 && win.minor<=3)) {
  HKEY temp;
  int r=0;
  if((r=RegOpenKeyExA(HKEY_CURRENT_USER,"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Accent",0,KEY_READ,&temp))==ERROR_SUCCESS) {
   auto accent_color=0UL;
   auto buf=4UL;
   if(win.minor==2) {
    if((r=RegQueryValueExA(temp,"ColorSet_Version3",nullptr,nullptr,(LPBYTE)&accent_color,&buf))==ERROR_SUCCESS) {
     col->r=ColorSet_Version3[accent_color][0][0];
     col->g=ColorSet_Version3[accent_color][0][1];
     col->b=ColorSet_Version3[accent_color][0][2];
     RegCloseKey(temp);
     return 3;
    } else {
     RegCloseKey(temp);
     return true;
    }
   } else {
    if((r=RegQueryValueExA(temp,"StartColor",nullptr,nullptr,(LPBYTE)&accent_color,&buf))==ERROR_SUCCESS) {
     col->r=GetRValue(accent_color);
     col->g=GetGValue(accent_color);
     col->b=GetBValue(accent_color);
     RegCloseKey(temp);
     return true;
    } else {
     RegCloseKey(temp);
     return false;
    }
   }
  } else {
   return false;
  }
 } else
  return false;
}
 
int main() {
 PersonalizationColor accent;
 PersonalizationColor background;
 if(!Win8GetAccentColor(&accent)) {
  std::cerr << "Cannot get accent color!" << endl;
  return 1;
 }
 if(!Win8GetBackgroundColor(&background)) {
  std::cerr << "Cannot get background color!" << endl;
  return 1;
 }
 std::cout << "Accent: " << accent.r << "," << accent.g << "," << accent.g << endl << "Background: " << background.r << "," << background.g << "," << background.b << endl;
 return 0;
}

Note1: It also work in Windows 8.1 without any edits
Note2: It can be ported to C with some editing.
Note3: I give a bonus code. You can use get_winver to get windows version(which i think is better than GetVersionEx)

Wednesday, October 22, 2014

[Lua]Get BPM/Tempo from WAV file

How do i get the tempo from WAV file? nah some Lua code can do that.

local function num2float (c)	-- http://stackoverflow.com/questions/18886447/convert-signed-ieee-754-float-to-hexadecimal-representation
	if c == 0 then return 0.0 end
	local c = string.gsub(string.format("%X", c),"(..)",function (x) return string.char(tonumber(x, 16)) end)
	local b1,b2,b3,b4 = string.byte(c, 1, 4)
	local sign = b1 > 0x7F
	local expo = (b1 % 0x80) * 0x2 + math.floor(b2 / 0x80)
	local mant = ((b2 % 0x80) * 0x100 + b3) * 0x100 + b4
	if sign then
		sign = -1
	else
		sign = 1
	end
	local n
	if mant == 0 and expo == 0 then
		n = sign * 0.0
	elseif expo == 0xFF then
		if mant == 0 then
			n = sign * math.huge
		else
			n = 0.0/0.0
		end
	else
		n = sign * math.ldexp(1.0 + mant / 0x800000, expo - 0x7F)
	end
	return n
end
 
local function int2char(int)
	return string.char(int%256)..string.char(math.floor(int/256%256))..string.char(math.floor(int/256/256%256))..string.char(math.floor(int/256/256/256))
end
 
local function char2int(char)
	return char:sub(1,1):byte()+char:sub(2,2):byte()*256+char:sub(3,3):byte()*65536+char:sub(4,4):byte()*16777216
end
 
function getWAVTempo(wav,verbose)
	local vp=function() end
	local f
	if verbose then vp=print end
	vp("getWAVTempo start!")
	if type(wav)=="userdata" then
		vp("#1 type is userdata. Assuming it's a file type!")
		f=wav
	else
		vp("#1 type is string. It's path to wav file")
		f=assert(io.open(wav,"rb"))
	end
	if verbose then vp=function(txt) print("["..string.format("%08X",f:seek("cur")).."] "..txt) end end
	local curSeek=f:seek("cur")
	local fileSize=f:seek("end")
	f:seek("set")
	if f:read(12)=="RIFF"..int2char(fileSize-8).."WAVE" then
		vp("WAV File header correct. Reading chunks!")
		while(f:seek("cur")~=fileSize)do
			local chunk=f:read(4)
			if(chunk=="acid")then
				vp("\"acid\" chunk found. Getting tempo data!")
				f:read(24)
				tempo=num2float(char2int(f:read(4)))
				vp("Tempo data found!")
				if type(wav)=="string" then f:close()
				else f:seek("set",curSeek) end
				return tempo
			else
				local size=char2int(f:read(4))
				vp("\""..chunk.."\" chunk found with size of "..size..". Skipping...")
				if size%2==1 then size=size+1 end
				f:seek("cur",size)
			end
		end
	else
		error("Invalid wav file!")
	end
	if verbose then print("Tempo data not found!") end
	if type(wav)=="userdata"then f:seek(curSeek)
	else f:close() end
	return 0
end

What do you need to do is:
  1. Save code above to file
  2. dofile it
  3. call getWAVTempo(file[,verbose])
    getWAVTempo Parameters:
    file - file handle(from io.open) or string to filename
    verbose - show more message. If you set this to true, you can see what's going on.
  4. a. If it returns 0, then the wav file does not come with embedded tempo data
    b. If it returns value more than 0, then that's the tempo. Please note that the decimals is stripped on return.
That's it.
Feel free to use some (or all) parts of code above.

Monday, October 20, 2014

[C#]Synaptics custom touchpad gesture code.

Nah, my laptop cannot use updated version of the synaptics touchpad driver. The driver that comes with it does lack of using some windows 8 touchpad gesture. I'm start to think, maybe i can access the Synaptics API and yes, that's possible. After a lot search in google, i have a code that allows to switch to Windows apps and show Charm bar with touchpad gesture.

If someone need it, feel free to check my source code(well, it's dirty written)(Requires Input Simulator)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Runtime.InteropServices;
using System.Diagnostics;
using SYNCTRLLib;
using WindowsInput;
 
namespace mytest2 {
    class MyPoint {
        public int x;
        public int y;
        public MyPoint(int a,int b) {
            x=a;
            y=b;
        }
        public MyPoint() {
            x=0;
            y=0;
        }
        public void Reset() {
            x=0;
            y=0;
        }
    }
    public struct Point {
        public int x,y;
    }
    class Program {
        // FingerState==589824=tap
        static MyPoint WinAppsPoint=new MyPoint(0,2000);
        static MyPoint CharmBarPoint=new MyPoint(5000,6143);
        static MyPoint FirstLast=new MyPoint();
        static SynAPICtrl apictrl=new SynAPICtrl();
        static SynDeviceCtrl devctrl=new SynDeviceCtrl();
        static SynPacketCtrl packetctrl=new SynPacketCtrl();
        static bool is_press=false;
        static int devh;
        [DllImport("user32.dll",CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
        public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo);
        [DllImport("user32.dll",CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
        public static extern int GetCursorPos(ref Point _);
        [DllImport("user32.dll",CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
        public static extern int SetCursorPos(int x,int y);
        [DllImport("user32.dll",CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
        public static extern int SendInput(uint n,Input[] list,int size);
        static double tempy1=0;
        static double tempy2=0;
        static void mycallback() {
            if(devctrl.LoadPacket(packetctrl)==1) {
                if(is_press) {
                    if(packetctrl.FingerState==589824) {    // Tap
                        FirstLast.Reset();
                        is_press=false;
                        return;
                    }
                    else if(packetctrl.FingerState<=512) {  // OK
                        is_press=false;
                        int myx=Math.Min(FirstLast.x,FirstLast.y),myy=Math.Max(FirstLast.x,FirstLast.y);
                        int r=(int)Math.Atan2(tempy2-tempy1,FirstLast.y-FirstLast.x);
                        Debug.WriteLine("Rotation: {0}",r);
                        if(myx>=WinAppsPoint.x && myy<=WinAppsPoint.y && FirstLast.x<FirstLast.y) {
                            Debug.WriteLine("Windows Apps Scroll");
                            Point temp=new Point();
                            GetCursorPos(ref temp);
                            SetCursorPos(0,0);
                            mouse_event(2|4,0,0,0,0);
                            SetCursorPos(temp.x,temp.y);
                        } else if(myx>=CharmBarPoint.x && myy<=CharmBarPoint.y && FirstLast.x>FirstLast.y && (r==3||r==(-3)||r==2||r==(-2))) {
                            Debug.WriteLine("Charm Bar");
                            InputSimulator myinpt=new InputSimulator();
                            myinpt.Keyboard.KeyDown(WindowsInput.Native.VirtualKeyCode.LWIN);
                            myinpt.Keyboard.KeyDown(WindowsInput.Native.VirtualKeyCode.VK_C);
                            myinpt.Keyboard.KeyUp(WindowsInput.Native.VirtualKeyCode.LWIN);
                            myinpt.Keyboard.KeyUp(WindowsInput.Native.VirtualKeyCode.VK_C);
                        }
                        return;
                    }
                    FirstLast.y=packetctrl.X;
                    tempy2=packetctrl.Y;
                }
                else if(packetctrl.FingerState>512 && packetctrl.FingerState!=589824) {
                    Debug.WriteLine("Press");
                    is_press=true;
                    FirstLast.x=packetctrl.X;
                    tempy1=packetctrl.Y;
                }
                //Console.WriteLine(packetctrl.FingerState);
                //Console.WriteLine("{0} {1}",packetctrl.X,packetctrl.Y);
            }
        }
        static void Main(string[] args) {
            apictrl.Initialize();
            apictrl.Activate();
            devh=apictrl.FindDevice(SynConnectionType.SE_ConnectionAny,SynDeviceType.SE_DeviceTouchPad,0);
            devctrl.Select(devh);
            devctrl.Activate();
            devctrl.OnPacket+=mycallback;
            while(true) {
                Thread.Sleep(16);
            }
        }
    }
}