2009-10-24 Making C executables smaller
There are some simple things that can be done to make C executables as small as possible.
#include <SDL/SDL.h> char quit = 0; int main() { SDL_Surface *screen,surface; SDL_Event e; SDL_Init( SDL_INIT_VIDEO ); screen = SDL_SetVideoMode( 400, 400, 32, SDL_SWSURFACE ); while(!quit) while(SDL_PollEvent(&e)>0) { if(e.type==SDL_MOUSEBUTTONDOWN) quit=1; if(e.type==SDL_KEYDOWN) quit=1; } SDL_Quit(); }
Compile: gcc main.c -o main -lSDL
strip is included in most unix systems. It deletes some info symbols from executables
You can also try sstrip which is advanced version of strip. You can download it from ELF kickers webpage.
Execute command: sstrip main
Size after: 1960 bytes
GC Masher Allows to bruteforce gcc options for smaller executable size.
I where using this options for gcsmaher
-O -O0 -O1 -O2 -O3 -Os -ffast-math -fomit-frame-pointer -fauto-inc-dec -mpush-args -mno-red-zone -mstackrealign
After runnig with this options executble size is 5175 bytes and best compiling options are all posible combination.
void _start()
asm ( \ "movl $1,%eax\n" \ "xor %ebx,%ebx\n" \ "int $128\n" \ );
One other thing is to archive your executable and cat it with unpack shell script.
a=/tmp/I;tail -n+2 $0|zcat>$a;chmod +x $a;$a;rm $a;exit
gcc -Os -ffast-math -fomit-frame-pointer -fauto-inc-dec -mpush-args -mno-red-zone -c small.c; ld -dynamic-linker /lib/ld-linux.so.2 small.o /usr/lib/libSDL.so -o small; strip -s -R .comment -R .gnu.version small;sstrip small; 7z a -tGZip -mx=9 small.gz small > /dev/null; cat unpack.header small.gz > small; chmod a+x small;rm small.gz small.o
Download Source
2009-10-08 Basic HTTP server
Basic HTTP server. When you type url it shows listing of your local directory. If you tipe with path to file name noting hapens
Use:
http://*.*.*.*:
http://*.*.*.*:
Run:
./server port
Compile:
gcc server.c -o server
C Source
Here is also python source. It runs on port:8081 and prints in terminal HTTP request. You can see what browser sends to server.
Py Source
2009-10-30 Linux assembler SDL
Open SDL window from asm. I tryed to open SDL window from asm. And that worked. Hardest thing is defining all structures from SDL headers. Windows opening and waiting while anykey will pressed.
include 'cdecl.inc' format ELF extrn SDL_Init extrn SDL_SetVideoMode extrn SDL_PollEvent extrn SDL_Quit ;video settings SDL_INIT_VIDEO equ 0x00000020 SDL_FULLSCREEN equ 0x80000000 ;event settings SDL_KEYDOWN equ 2 SDL_MOUSEBUTTONDOWN equ 5 ;programm settings SCREEN_WIDTH equ 800 SCREEN_HEIGHT equ 600 SCREEN_BPP equ 24 struc SDL_keysym { .scancode db 0 .sym dd 0 .mod dd 0 .unicode dd 0 } struc SDL_KeyboardEvent { .type db 0 .which db 0 .state db 0 .keysym SDL_keysym } struc SDL_Event { .type db 0 union SDL_KeyboardEvent .empty db 0,0,0 } section '.text' executable public _start _start: ccall SDL_Init,SDL_INIT_VIDEO ccall SDL_SetVideoMode, SCREEN_WIDTH , SCREEN_HEIGHT , SCREEN_BPP , SDL_FULLSCREEN ;try to make while loop while_run: while_polleEvent: ccall SDL_PollEvent, event cmp eax, 0 je while_polleEventquit cmp byte [event.type], SDL_KEYDOWN jne while_polleEvent mov byte [run], 0 jmp while_polleEvent while_polleEventquit: ; if run != 1 quit cmp byte [run], 1 je while_run ccall SDL_Quit, 0 mov eax, 1 xor ebx, ebx int 80h section '.data' writeable event SDL_Event run db 1
Compile with lines:
fasm sdl.asm sdl.o
ld -dynamic-linker /lib/ld-linux.so.2 sdl.o /usr/lib/libSDL.so -o sdl
Dowload Source
2009-11-08 Linux Assembler Make Directory
Code for creating file:
format ELF executable include 'cdecl.inc' include 'syscall.inc' mode_t equ dd segment readable executable start: mov eax, SYS_MKDIR mov ebx, path mov ecx, [mode] int 80h mov eax, SYS_EXIT xor ebx, ebx int 80h segment readable writeable path db "dir",0 mode mode_t 0777o
2009-11-30 Linux ShellCode 1
First shell code writened from example. Shell code is very interesting way how to execute some code.
asm source:
use32 xor eax, eax inc eax xor ebx, ebx int 80h
fasm code.asm code.bin
bin2hex output:
\x31\xc0\x40\x31\xdb\xcd\x80C source:
#include <stdio.h> char code[] = "\x31\xc0\x40\x31\xdb\xcd\x80"; int main() { void (*ret)(); ret = (void (*)())code; ret(); printf("Nope it not working\n"); }
gcc main.c -o main
run ./main nothing happens. That exactly that code do exits from programm
Source
My variant of Bin2Hex
2009-11-30 ARP analyzer
Research in ARP protocol. Watch ARP packets , count them and show in list.
Usage
./arpsni eth0
Version 0.1[2009nov30]
ArpSni.0.1
2009-12-12 Linux keyboard LED
#include <stdlib.h> #include <fcntl.h> #include <sys/syscall.h> #include <linux/kd.h> int main( int argc , char **argv ) { int rc,i; if (argc != 4) exit(0); rc = syscall(SYS_open,"/dev/console",O_WRONLY,7*64+7*8+7); //open cosole if (rc == 0) rc = 1; i = (argv[1][0]-'0')*2+(argv[2][0]-'0')*4+(argv[3][0]-'0'); ioctl( rc , KDSETLED , i ); return 0; }
2009-12-14 Linux PC speaker
int main() { int rc,i; note *curent_song; curent_song = song; struct timespec t1; rc = syscall(SYS_open,"/dev/console",O_WRONLY,7*8*64+7*8+7); //open cosole if (rc == 0) rc = 1; ioctl( rc, KIOCSOUND , 0 ); ioctl( rc , KDSETLED , 7 ); i = 0; while ( curent_song[i].n != 0 ) { ioctl( rc , KIOCSOUND , curent_song[i].n ); msleep( (curent_song[i].t) ); ioctl( rc , KDSETLED , i&0x0007 ); i++; } ioctl( rc , KDSETLED , 0 ); ioctl( rc, KIOCSOUND , 0 ); return 0; }
2009-12-25 Linux Format String Attack 1
Format string attack is attack for C formated strings. Format string function is prinrf() there are other
functions that support format string.
C code for bad used printf():
int main( int argc, char **argv ) { static int i = 0; char text[1000]; strcpy(text, argv[1]); printf("%.8x\n",&i); printf("No way it never will works because value of i=%d\n",i); printf( text ); printf("\nValue of i=%d\n",i); return 0; }First output is adress of static i
Than we outputing values of i and call printf() with first argument fo prgramm.
and then watching value if i
Run: ./e1 'Halolo'
Output:
08049674 No way it never will works because value of i=0 Halolo Value of i=0Run: ./e1 'Halolo%s'
Output:
08049674 No way it never will works because value of i=0Halolo(null) Value of i=0
Run: ./e1 $'\x74\x96\x04\x08_%x'
Output:
08049674 No way it never will works because value of i=0 t�_0 Value of i=0
Read about %n in format string:
Run: ./e1 $'\x74\x96\x04\x08_%x_%n'
Output:
08049674 No way it never will works because value of i=0 Segmentation faultRun: ./e1 $'\x74\x96\x04\x08_%x_%x_%x_%x_%x_%n'
Output:
08049674 No way it never will works because value of i=0 t�_0_8_40_4_4_ Value of i=16Run: ./e1 $'\x74\x96\x04\x08_%x_%x_%x_%x_%.1201x_%n'
Output:
08049674 No way it never will works because value of i=0 t�_0_8_40_4_000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000004_ Value of i=1216
Now you can input almost any value to i
2010-01-24 Linux Local Descriptor Table
If 0x80**** adreeses is default nope. You can setup your own. Compiler will not see them
but you can do it. Setup LDT and you will see it.
use32 mov dword [0] ,"Hall" mov dword [4] ,"Ball" mov dword [8] ,"Mall" mov dword [12],0x00000000yes everything starts from 0x0
#include <stdlib.h> #include <stdio.h> #include <sys/syscall.h> #include <sys/types.h> #include <asm/ldt.h> char new_segment[16]; int main() { int r; struct user_desc *ldt; ldt = (struct user_desc*)malloc(sizeof(struct user_desc)); ldt->entry_number = 0; ldt->base_addr = ((unsigned long)&new_segment); ldt->limit = 16; ldt->seg_32bit = 0x1; ldt->contents = 0x0; ldt->read_exec_only = 0x0; ldt->limit_in_pages = 0x0; ldt->seg_not_present = 0x0; ldt->useable = 0x1; printf("Start\n"); r = syscall( __NR_modify_ldt, 1 , ldt , sizeof(struct user_desc) ); if ( r == -1 ) { printf("Sorry\n"); exit( 0 ); } asm("pushl %ds"); asm("movl $0x7, %eax"); /* 0111: 0-Index 1-Using the LDT table 11-RPL of 3 */ asm("movl %eax, %ds"); asm(".byte 0xc7,0x5,0x0,0x0,0x0,0x0,0x48,0x61,\ 0x6c,0x6c,0xc7,0x5,0x4,0x0,0x0,0x0,\ 0x42,0x61,0x6c,0x6c,0xc7,0x5,0x8,0x0,\ 0x0,0x0,0x4d,0x61,0x6c,0x6c,0xc7,0x5,\ 0xc,0x0,0x0,0x0,0x0,0x0,0x0,0x0"); asm("popl %ds"); printf("End\n"); printf("Segment [%s]\n",new_segment); free( ldt ); return 0; }asm(".byte ... ") is code.bin
Compile:
fasm code.asm code.bin
gcc main.c -o main
Source
2010-02-23 Linux antidebug 1
When ptrace is used for programm debugin then only one ptrace can be attached to programm
when we trying run ptrace with PTRACE_TRACEME then we get -1. I tested with gdb,ald. Also this method should
work with IDApro
#include <stdlib.h> #include <stdio.h> #include <sys/ptrace.h> long int ptraced() { return (ptrace(PTRACE_TRACEME, 0, 0, 0) == -1); } int main() { if ( ptraced() ) { printf("Ptraced!\n"); } return 0; }
Source
2010-02-26 Linux antidebug 2
This is dirty solution it checks programms argv[0] name with your defined name
when running debuger such as gdb or ald name is chaned to fullpath name
user defined name from terminal is './main'.
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <sys/types.h> int main( int argc , char **argv ) { pid_t pid,ppid; FILE *f; char str[128]; char spid[10]; //openfile and write ppid f = fopen( "pid.txt" , "w" ); pid = getpid(); fprintf(f,"%d ",pid); fclose( f ); f = fopen( "pid.txt" , "r" ); fscanf( f , "%s" , spid ); fclose( f ); strcpy( str , "cat /proc/" ); strcat( str , &spid[0] ); strcat( str , "/cmdline"); printf( "[%s]\n", spid ); system( str ); printf("\n"); }
Dirty function that makes dirty solution at one place
int badppid( const char *real_name ) { pid_t pid,ppid; FILE *f; char str[128]; char spid[10]; f = fopen( "pid.txt" , "w" ); pid = getpid(); fprintf(f,"%d ",pid); fclose( f ); f = fopen( "pid.txt" , "r" ); fscanf( f , "%s" , spid ); fclose( f ); strcpy( str , "cat /proc/" ); strcat( str , &spid[0] ); strcat( str , "/cmdline > name.txt"); system( str ); f = fopen( "name.txt" , "r" ); fscanf( f , "%s" , str ); fclose( f ); if ( strncmp(str,real_name,strlen(real_name)) != 0 ) { return -1; } return 0; }
Source
2010-03-05 Linux antidebug 3
Now we will try to make disasm output whery unclear. We make jump with eax register
Programm 1
main: push lbl+1 pop eax jmp eax lbl: db 0xe8 mov eax, 4 mov ebx, 1 mov ecx, msg1 mov edx, msg1_size int 80h mov eax, 1 mov ebx, 0 int 80hOutput is same as source. Nothing changes
Dissassembler output 1
│ ....... ! main: ;xref o80482d7 │ │ ....... ! push offset_804837d │ │ 8048379 ! pop eax │ │ 804837a ! jmp eax │ │ 804837c db 0e8h │ │ 804837d ! │ │ ....... ! offset_804837d: ;xref o8048374 │ │ ....... ! mov eax, 4 │ │ 8048382 ! mov ebx, 1 │ │ 8048387 ! mov ecx, strz_I_am_running__8049568 │ │ 804838c ! mov edx, 0eh │ │ 8048391 ! int 80h │ │ 8048393 ! mov eax, 1 │ │ 8048398 ! mov ebx, 0 │ │ 804839d ! int 80hHere we add only one instruction. We get jump adress and add 1. Disasm cannot calculate adress of jmp.
Programm 2
Like in first programm disasm think that we push correct adress and disasm it. And our byte 0xe9 is used
for disasm output. That nice.
main: push lbl pop eax inc eax jmp eax lbl: db 0xe9 mov eax, 4 mov ebx, 1 mov ecx, msg1 mov edx, msg1_size int 80h mov eax, 1 mov ebx, 0 int 80h
Dissassembler output 2
│ ....... ! main: ;xref o80482d7 │ │ ....... ! push offset_804837d │ │ 8048379 ! pop eax │ │ 804837a ! inc eax │ │ 804837b ! jmp eax │ │ 804837d ! │ │ ....... ! offset_804837d: ;xref o8048374 │ │ ....... ! jmp 804883ah │ │ 8048382 add [ebx+1], bh │ │ 8048388 mov ecx, 8049568h │ │ 804838d mov edx, 0eh │ │ 8048392 int 80h │ │ 8048394 mov eax, 1 │ │ 8048399 mov ebx, 0 │ │ 804839e int 80h
Now we add nop instruction after every line of our code. It doesnt have any imapct on programm work.
Programm 3
main: push lbl pop eax inc eax jmp eax lbl: db 0xe9 mov eax, 4 nop mov ebx, 1 nop mov ecx, msg1 nop mov edx, msg1_size int 80h mov eax, 1 mov ebx, 0 jmp lbl2+1 lbl2: db 0xe9 int 80hDisasm output now is very nice. Output isnt very good. For first time when you view this output it is very unclear
about what exactly is done by this code.
Dissassembler output 3
│ ....... ! main: ;xref o80482d7 │ │ ....... ! push offset_804837d │ │ 8048379 ! pop eax │ │ 804837a ! inc eax │ │ 804837b ! jmp eax │ │ 804837d ! │ │ ....... ! offset_804837d: ;xref o8048374 │ │ ....... ! jmp 804883ah │ │ 8048382 add [eax+1bbh], dl │ │ 8048388 add [eax+49578b9h], dl │ │ 804838e or [eax+0ebah], dl │ │ 8048394 add ch, cl │ │ 8048396 cmp byte ptr [eax+1], 0bbh │ │ 804839d add [eax], al │ │ 804839f add [eax], al │ │ 80483a1 jmp 80483a4h │ │ 80483a3 jmp 98950475h
Here is one more way how to make unclear jumo to other place. We using function
and inside function we change return adress by 1.
Programm 4
Thats also works fine. Disasm dont know real return adress ans and use 0xe8 as he think is better.
main: call fun db 0xe8 mov eax, 4 mov ebx, 1 mov ecx, msg1 mov edx, msg1_size int 80h mov eax, 1 mov ebx, 0 int 80h fun: pop ebp inc ebp push ebp ret
Dissassembler output 4
│ ....... ! main: ;xref o80482d7 │ │ ....... ! call sub_804839c │ │ 8048379 ! call 8048836h │ │ 804837e ! add [ebx+1], bh │ │ 8048384 ! mov ecx, strz_I_am_running__8049568 │ │ 8048389 ! mov edx, 0eh │ │ 804838e ! int 80h │ │ 8048390 ! mov eax, 1 │ │ 8048395 ! mov ebx, 0 │ │ 804839a ! int 80h │ │ 804839c ! │ │ ....... ! ;----------------------- │ │ ....... ! ; S U B R O U T I N E │ │ ....... ! ;----------------------- │ │ ....... ! sub_804839c: ;xref c8048374 │ │ ....... ! pop ebp │ │ 804839d ! inc ebp │ │ 804839e ! push ebp │ │ 804839f ! ret
Source
2010-04-24 CVS 2010-1160 Exploiting nano
CVE-2010-1160 Nano Changed File Symlink Privilege Escalation
Usualy if I have to edit some file I am using nano editor.
It is almost on every distribution and easy and fast to use. Some time ago i hated vim
beacouse of Ctrl-D =] and that way used nano or pico. Now I know how to exit from vim :q!. After this bug
reported in CVE i was exited to check it out in real life. It is first bug that i have fully tested.
This bug is fixed in newest versions. Testing all nano version this bug works
on < 2.1.7 versions now on my system is latest nano version and I have
compiled many < 2.1.7 versions to test this bug.
To get your nano version run:
$ nano -V
When user is editing file nano don't check if it is edited by some
one else. When saving file it simply save it and dont check if it was modified. If file was changed by some one else
then nano will overwrite it with his text. But it can be changed to symlink that points to other file. How to use it in real life:
1) Open file with nano
2) Change file or set symlink
3) Make changes in file and save file in nano
4) See result in symlinked file
Everytning looks like
$nano text.txt
Now some one do:
$ls -s empty.txt text.txt
Nano save
whach you save in text.txt
In python it looks like:
os.remove( "text.txt" ) open( "empty.txt" , "w" ).close() os.symlink( "empty.txt" , "text.txt"Python step by step
If you are root and opening file with owner isnt you. Than owner while you
editing his file can set
symlink to some "/etc/important.conf" and you will overwrite it with some
other unrelated info. This can make some harm to your system.
How can it be exploited in real life by "small unpreviliged user". Make some interesting file
that root will interested in. Make some process that whachs nanos running in system. If nano opened file is our , symlink it.
1)Detect running nano in system
2)Check with file is opened
3)If file is yours make symlink
Nano catch
Script is only for user and dont work if you try to symlink root opened nano. It makes
all steps as described above. Change script variables for your tests:
debug = True nano = "nano-2.0.9" user = "user" sym_path="/home/user/empty.txt"Tested only with python 2.6.5
Simply be uptodated or if you using old nano dont open with privileged user unpriveleged user files.
It will save you from this bug.
Linkage:
[1] http://osvdb.org/show/osvdb/63872
[2] http://cve.mitre.org/cgi-bin/cvename.cgi?name=2010-1160
[3] http://drosenbe.blogspot.com/2010/03/nano-as-root.html
[4] http://svn.savannah.gnu.org/viewvc/trunk/nano/ChangeLog?revision=4503&root=nano&view=markup