loading...

(Write-up) pwnable.kr :: collision

aibhstin profile image Aibhstin ・2 min read

This is a write-up for the second challenge from pwnable.kr, 'collision'.

The main function of the vulnerable program is the following:

int main(int argc, char* argv[]){
        if(argc<2){
                printf("usage : %s [passcode]\n", argv[0]);
                return 0;
        }
        if(strlen(argv[1]) != 20){
                printf("passcode length should be 20 bytes\n");
                return 0;
        }

        if(hashcode == check_password( argv[1] )){
                system("/bin/cat flag");
                return 0;
        }
        else
                printf("wrong passcode.\n");
        return 0;
}

We can see that we need to supply a command-line argument to the program in order to get the flag. We can see that it has to be 20 characters in length, and it has to cause the function check_password to return a value equal to hashcode.

unsigned long hashcode = 0x21DD09EC;                                                                            
unsigned long check_password(const char* p){                                                                    
        int* ip = (int*)p;                                                                                      
        int i;
        int res=0;
        for(i=0; i<5; i++){
                res += ip[i];
        }
        return res;
}

This is the rest of the program. Hashcode is equal to 0x21DD09EC, or 568134124 in decimal.

For the function, it's best to step through it line by line:

int *ip = (int*)p;

This casts the string given as input into an array of integers, called ip.

int i;

This declares an integer variable called i.

int res=0;

This declares an integer variable called res and sets it to 0. This will be used to store the result.

for(i=0; i<5; i++){

This loops 5 times, using i as the index.

res += ip[i];

res is incremented by the value stored in the array ip at index i. From these lines, we can see that it's the first 5 characters that are used to calculate the hashcode. The password needs to be 20 bytes long. Therefore, we need 20 character bytes that generate a hashcode equal to 0x21DD09EC. A character is 1 byte, but an integer is 4, therefore the 20 characters of the input will become just 5 integers.

> irb
irb(main):001:0> 0x21DD09EC
=> 568134124
irb(main):002:0> 568134124 / 5
=> 113626824
irb(main):003:0> 568134124 - (113626824 * 4)
=> 113626828
irb(main):004:0> 113626824 * 4 + 113626828 == 0x21DD09EC
=> true

Now we now the 5 integers we need to create the hashcode, we can use Ruby pwntools to create the characters we need.

irb(main):010:0> p32(113626824) * 4 + p32(113626828)
=> "\xC8\xCE\xC5\x06\xC8\xCE\xC5\x06\xC8\xCE\xC5\x06\xC8\xCE\xC5\x06\xCC\xCE\xC5\x06"

Now that we have the character string we need, we can printf it as a commandline argument to the program and get the flag.

col@pwnable:~$ ./col ` printf "\xC8\xCE\xC5\x06\xC8\xCE\xC5\x06\xC8\xCE\xC5\x06\xC8\xCE\xC5\x06\xCC\xCE\xC5\x06"`
<-- FLAG OMITTED -->

Posted on by:

aibhstin profile

Aibhstin

@aibhstin

I'm an Ethical Hacking & Cybersecurity student and a Haskell programmer.

Discussion

markdown guide