Episodes
Wednesday Jan 03, 2007
Special Macros in Makefile
Wednesday Jan 03, 2007
Wednesday Jan 03, 2007
In addition to those macros which you can create yourself, there are a few macros which are used internally by the make program. Here are some of those, listed below:
CC Contains the current C compiler. Defaults to cc. CFLAGS Special options which are added to the built-in C rule. $@ Full name of the current target. $? A list of files for current dependency which are out-of-date. $< The source file of the current (single) dependency.
Wednesday Dec 06, 2006
buffer overflow
Wednesday Dec 06, 2006
Wednesday Dec 06, 2006
A security problem in OS -- buffer overflow. In computer security and programming, a buffer overflow, or buffer overrun, is a programming error which may result in a memory access exception and program termination, or in the event of the user being malicious, a breach of system security. A buffer overflow is an anomalous condition where a process attempts to store data beyond the boundaries of a fixed length buffer. The result is that the extra data overwrites adjacent memory locations. The overwritten data may include other buffers, variables and program flow data. Buffer overflows may cause a process to crash or produce incorrect results. They can be triggered by inputs specifically designed to execute malicious code or to make the program operate in an unintended way. As such, buffer overflows cause many software vulnerabilities and form the basis of many exploits. Sufficient bounds checking by either the programmer or the compiler can prevent buffer overflows. An open source computer security project which provides information about security vulnerabilities and aids in penetration testing and IDS signature development is Metasploit Project. The contents hereafter is copied from www.governmentsecurity.org A buffer overflow problem is based in the memory where the program stores it's data. Why's that, you ask. Well because what buffer overflow do is overwrite expecific memory places where should be something you want, that will make the program do something that you want. Well some of you right now are thinking "WOW, I know how buffer overflow works", but you still don't know how to spot them. Let's follow a program and try to find and fix the buffer overflow ------ Partial code below-------- main(int argc, char **argv) { char *somevar; char *important; somevar = (char *)malloc(sizeof(char)*4); important = (char *)malloc(sizeof(char)*14); strcpy(important, "command"); /*This one is the important variable*/ stcrpy(somevar, argv[1]); ..... Code here .... } .... Other functions here .... ------- End Of Partial Code ------ So let's say that important variable stores some system command like, let's say "chmod o-r file", and since that file is owned by root the program is run under root user too, this means that if you can send commands to it, you can execute ANY system command. So you start thinking. How the hell can I put something that I want in the important variable. Well the way is to overflow the memory so we can reach it. But let's see variables memory addresses. To do that you need to re-written the code. Check the following code. --------- Partial Code ------------ main (int argc, char **argv) { char *somevar; char *important; somevar=(char *)malloc(sizeof(char)*4); important=(char *)malloc(sizeof(char)*14); printf("%p\n%p", somevar, important); exit(0); rest of code here } --------- End of Partial Code -------- Well we added 2 lines in the source code and left the rest unchanged. Let's see what does two lines do. The printf("%p\n%p", somevar, important); line will print the memory addresses for somevar and important variables. The exit(0); will just keep the rest of the program running after all you don't want it for nothing, your goal was to know where is the variables are stored. After running the program you would get an output like, you will probably not get the same memory addresses: 0x8049700 <----- This is the address of somevar 0x8049710 <----- This is the address of important As we can see, the important variable is next somevar, this will let us use our buffer overflow skills, since somevar is got from argv[1]. Now, we know that one follow the other, but let's check each memory address so we can have the precise notion of the data storage. To do this let's re-write the code again. -------- Partial code --------- main(int argc, char **argv) { char *somevar; char *important; char *temp; /* will need another variable */ somevar=(char *)malloc(sizeof(char)*4); important=(char *)malloc(sizeof(char)*14); strcpy(important, "command"); /*This one is the important variable*/ stcrpy(str, argv[1]); printf("%p\n%p\n", somevar, important); printf("Starting To Print memory address:\n"); temp = somevar; /* this will put temp at the first memory address we want */ while(temp < important + 14) { /* this loop will be broken when we get to the last memory address we want, last memory address of important variable */ printf("%p: %c (0x%x)\n", temp, *temp, *(unsigned int*)temp); temp++; } exit(0); rest of code here } ------ End Of partial Code ------ Now let's say that the argv[1] should be in normal use send. So you just type in your prompt: $ program_name send You'll get an output like: 0x8049700 0x8049710 Starting To Print memory address: 0x8049700: s (0x616c62) 0x8049701: e (0x616c) 0x8049702: n (0x61) <---- each of this lines represent a memory address 0x8049703: d (0x0) 0x8049704: (0x0) 0x8049705: (0x0) 0x8049706: (0x0) 0x8049707: (0x0) 0x8049708: (0x0) 0x8049709: (0x19000000) 0x804970a: (0x190000) 0x804970b: (0x1900) 0x804970c: (0x19) 0x804970d: (0x63000000) 0x804970e: (0x6f630000) 0x804970f: (0x6d6f6300) 0x8049710: c (0x6d6d6f63) 0x8049711: o (0x616d6d6f) 0x8049712: m (0x6e616d6d) 0x8049713: m (0x646e616d) 0x8049714: a (0x646e61) 0x8049715: n (0x646e) 0x8049716: d (0x64) 0x8049717: (0x0) 0x8049718: (0x0) 0x8049719: (0x0) 0x804971a: (0x0) 0x804971b: (0x0) 0x804971c: (0x0) 0x804971d: (0x0) $ Nice isn't it? You can now see that there exist 12 memory address empty between somevar and important. So let's say that you run the program with a command line like: $ program_name send------------newcommand You'll get an output like: 0x8049700 0x8049710 Starting To Print memory address: 0x8049700: s (0x646e6573) 0x8049701: e (0x2d646e65) 0x8049702: n (0x2d2d646e) 0x8049703: d (0x2d2d2d64) 0x8049704: - (0x2d2d2d2d) 0x8049705: - (0x2d2d2d2d) 0x8049706: - (0x2d2d2d2d) 0x8049707: - (0x2d2d2d2d) 0x8049708: - (0x2d2d2d2d) 0x8049709: - (0x2d2d2d2d) 0x804970a: - (0x2d2d2d2d) 0x804970b: - (0x2d2d2d2d) 0x804970c: - (0x2d2d2d2d) 0x804970d: - (0x6e2d2d2d) 0x804970e: - (0x656e2d2d) 0x804970f: - (0x77656e2d) 0x8049710: n (0x6377656e) <--- memory address where important variable starts 0x8049711: e (0x6f637765) 0x8049712: w (0x6d6f6377) 0x8049713: c (0x6d6d6f63) 0x8049714: o (0x616d6d6f) 0x8049715: m (0x6e616d6d) 0x8049716: m (0x646e616d) 0x8049717: a (0x646e61) 0x8049718: n (0x646e) 0x8049719: d (0x64) 0x804971a: (0x0) 0x804971b: (0x0) 0x804971c: (0x0) 0x804971d: (0x0) Hey cool, newcommand got over command. Now it does something you want, instead of something he was supposed to do. NOTE: Remember sometimes those spaces between somevar and important can have other variables instead of being empty, so check their values and send them to the same address, or the program can crash before getting to the variable that you modified. Now let's think a little. Why does this happen? As you can see in the source code somevar is declared before important, this will make, most of the times, that somevar will be first in memory. Now, let's check how each one is got. Somevar gets it's value from argv[1], and important gets it from strcpy() function, but the real problem is that important value is assign first so when you assign value to somevar that is before it important can be overwritten. This program could be patched against this buffer overflow switching those two lines, becoming : strcpy(somevar, argv[1]); strcpy(important, "command"); If this was the way that the program was done even if you give an argument that would get into the memory address of important, it will be overwritten by the true command, since after getting somevar, is assign the value command to important. This kind of buffer overflow, is a heap buffer overflow. Like you probably has seen they are really easy to do in theory but, in the real world, it's not really easy to do them, after all the example I gave was a really dumb program right? It's a real pain in the ass to find those important variables, and also to overflow that variable you need to be able to write to one that is in a lower memory address, most of times all this conditions
Monday Dec 04, 2006
Mutex vs. Semaphore
Monday Dec 04, 2006
Monday Dec 04, 2006
In short, you can view mutex as a binary semaphore --a semaphore whose value is 0 or 1. Normally, mutex runs faster than semaphore. However, kernel mutex may have the same cost as semaphore. A good description on Mutex vs. Semaphore is presented by Niclas Winquist at http://koti.mbnet.fi/niclasw/MutexSemaphore.html. I copy it as hereafter: Mutex: Is a key to a toilet. One person can have the key - occupy the toilet - at the time. When finished, the person gives (frees) the key to the next person in the queue. Officially: "Mutexes are typically used to serialise access to a section of re-entrant code that cannot be executed concurrently by more than one thread. A mutex object only allows one thread into a controlled section, forcing other threads which attempt to gain access to that section to wait until the first thread has exited from that section." Ref: Symbian Developer Library (A mutex is really a semaphore with value 1.) Semaphore: Is the number of free identical toilet keys. Example, say we have four toilets with identical locks and keys. The semaphore count - the count of keys - is set to 4 at beginning (all four toilets are free), then the count value is decremented as people are coming in. If all toilets are full, ie. there are no free keys left, the semaphore count is 0. Now, when eq. one person leaves the toilet, semaphore is increased to 1 (one free key), and given to the next person in the queue. Officially: "A semaphore restricts the number of simultaneous users of a shared resource up to a maximum number. Threads can request access to the resource (decrementing the semaphore), and can signal that they have finished using the resource (incrementing the semaphore)." Ref: Symbian Developer Library
Tuesday Nov 28, 2006
PHP preg_replace example
Tuesday Nov 28, 2006
Tuesday Nov 28, 2006
The above example will output: April1,2003
Saturday Nov 25, 2006
Tuesday Oct 17, 2006
Monitor 2nd
Tuesday Oct 17, 2006
Tuesday Oct 17, 2006
Someone still have questions about monitor, I clear some issues as hereafter: 1. Only ONE process can access(enter) into a monitor block(object). 2. The wait() will put a process in sleep and leave(release) the monitor. 3. The signal() will re-active a sleeping process. 4. The monitor already has the capability to guard ONLY one process can access the code, why we need the wait() and signal() ? Answer: To avoid dead-lock situation.
Monday Oct 16, 2006
Monitor in Java
Monday Oct 16, 2006
Monday Oct 16, 2006
Monitor is implemented in Java vm. You can get some ideas from http://www.artima.com/insidejvm/ed2/threadsynch3.html Java provides two built-in ways to identify monitor regions in your programs: synchronized statements and synchronized methods. These two mechanisms, which implement the mutual exclusion aspect of synchronization, are supported by the Java virtual machine's instruction set.
Synchronized Statements
To create a synchronized statement, you use the synchronized keyword with an expression that evaluates to an object reference, as in thereverseOrder()
method below:
class KitchenSync { private int[] intArray = new int[10]; void reverseOrder() { synchronized (this) { int halfWay = intArray.length / 2; for (int i = 0; i < halfWay; ++i) { int upperIndex = intArray.length - 1 - i; int save = intArray[upperIndex]; intArray[upperIndex] = intArray[i]; intArray[i] = save; } } } // ... }In the above case, the statements contained within the synchronized block will not be executed until a lock is acquired on the current object (
this
). If instead of a this
reference, the expression yielded a reference to another object, the lock associated with that object would be acquired before the thread continued. If the expression yields a reference to an instance of class Class
, the lock associated with the class is acquired.
Synchronized Methods
To synchronize an entire method, you just include the synchronized keyword as one of the method qualifiers, as in:class HeatSync { private int[] intArray = new int[10]; synchronized void reverseOrder() { int halfWay = intArray.length / 2; for (int i = 0; i < halfWay; ++i) { int upperIndex = intArray.length - 1 - i; int save = intArray[upperIndex]; intArray[upperIndex] = intArray[i]; intArray[i] = save; } } // ... }The Java virtual machine does not use any special opcodes to invoke or return from synchronized methods. When the virtual machine resolves the symbolic reference to a method, it determines whether the method is synchronized. If so, the virtual machine acquires a lock before invoking the method. For an instance method, the virtual machine acquires the lock associated with the object upon which the method is being invoked. For a class method, it acquires the lock associated with the class to which the method belongs (it locks a
Class
object). After a synchronized method completes, whether it completes by returning or by throwing an exception, the virtual machine releases the lock.Monday Oct 16, 2006
monitor in theory
Monday Oct 16, 2006
Monday Oct 16, 2006
This is a kind of sudo-code example showing monitor in a writer-reader situation: (modify from Gary Nutt's book) monitor reader_writer { int readerNum=0; boolean busy = FALSE; condition okToRead, okToWrite; public: startRead{ if (busy) okToRead.wait(); //put the process in sleep readerNum ++; okToRead.signal(); //reactive the process }; finishRead{ readerNum --; if(readerNum == 0) okToWrite.signal(); }; startWrite{ if((readerNum != 0) || busy) okToWrite.wait(); busy = TRUE; }; finishWrite{ busy = FALSE; okToWrite.signal(); //signal the writing processes okToRead.signal(); //signal the reading processes }; };
Monday Oct 16, 2006
PIPE with 2 child process
Monday Oct 16, 2006
Monday Oct 16, 2006
another example of PIPE with 2 child process
#include
Monday Oct 16, 2006
Interprocess communication via Pipe
Monday Oct 16, 2006
Monday Oct 16, 2006
Hereafter is an example of using PIPE for IPC:
#include