Sunday, January 19, 2014

GhostInTheShellCode Write-Up lugkist


We were given a file full of some random fix length strings.
[Wani@Linux gits]$ cat lugkist
GVZSNG
AXZIOG
YNAISG
ASAIUG
IVPIOK
AXPIVG
PVZIUG
AXLIEG
YUPISK
AXASEG
GVZSSG
AXZSKG
PVPIXK
ZNASKG
LVPSOG
PVZSVK
IVASNG
GVPIEK
IVPSNK
PNZIKK
YNASSG
TVPSSK
LVZIVG
PVLSKG
PVLIVG
TNLING
ANLSUG
PVPSEG
AVASVK
LNLSXG
PVPSKK
LVPSXK
TNASXG
AXPSVG
GNLIUG
LNLSNG
TVLIOK
AVZINK
GNZSXG
IVAIVG
TVPIUK
LVLSSG
IVLSEG
AVLISK
YVAIKK
ZKPING
YVPIKG
LNZSUG
PVZSOG
AXZISG
YVASOK
ZNAING
AXPSUG
IVLSVG
AXLIKG
GVZIXG
IVASUG
TXGIEK
PNZIEK
YVLIXK
IVZSEG
AXLSOG
[Wani@Linux gits]$ 

Hint provided was: "Hints: lugkist: SLTIYG". On googling, one quickly comes across: http://nintendo-entertainment-system.weebly.com/game-cheats-2.html, which tells us that these codes are game genie codes. So, obviously, we needed to decode them.
Now, since online decoders required the person to enter the 62 codes manually, to decode them, I needed to write a program. So, I read the rules of decoding here and wrote the following python program:
def func(op):
    if op == 'A':
        return 0x0
    if op == 'P':
 return 0x1
    if op == 'Z':
 return 0x2
    if op == 'L':
 return 0x3
    if op == 'G':
 return 0x4
    if op == 'I':
 return 0x5
    if op == 'T':
 return 0x6
    if op == 'Y':
 return 0x7
    if op == 'E':
 return 0x8
    if op == 'O':
 return 0x9
    if op == 'X':
 return 0xA
    if op == 'U':
 return 0xB
    if op == 'K':
 return 0xC
    if op == 'S':
 return 0xD
    if op == 'V':
 return 0xE
    if op == 'N':
 return 0xF

import sys

n = [func(x) for x in sys.argv[1]]

address = 0x8000 + ((n[2] & 7) << 12)| ((n[4] & 7) << 8) | ((n[3] & 8) << 8) | ((n[1] & 7) << 4) | ((n[0] & 8) << 4) |  (n[3] & 7) |  (n[2] & 8);
data = ((n[1] & 7) << 4) | ((n[0] & 8) << 4) | (n[0] & 7) | (n[5] & 8);

print "%0x %0x"%(address, data)

Lets see what the output is!
[Wani@Linux gits]$ while read line ; do python genie.py $line ; done < lugkist  
af65 64
a125 20
8575 77
8355 50
9165 6d
9625 20
a365 61
b025 20
9535 3f
8825 20
ad65 64
ac25 20
9265 69
8c75 72
9965 63
ae65 69
8f65 65
9065 6c
9f65 6d
a475 79
8d75 77
9d65 6e
a665 63
bc65 61
b665 61
b775 76
bb75 70
9865 61
8e65 68
ba75 73
9c65 69
9a65 6b
8a75 76
9e25 20
b375 74
bf75 73
b165 6e
a765 68
aa75 74
8665 65
9365 6e
bd65 63
b865 65
b565 68
8465 6f
9745 42
9465 67
ab75 73
a965 61
a525 20
8965 6f
8775 72
9b25 20
be65 65
b425 20
a265 64
8b65 65
c025 2e
a075 79
b265 6f
a865 65
b925 20
[Wani@Linux gits]$ 

The second column seemed to have numbers which seem printable characters. But the address are not. So, making a few changes:
address_ = int(str("%0x"%address), 16) 
print "%d %d"%(address_, data)

Lets see the output now:
[Wani@Linux gits]$ while read line ; do python genie.py $line ; done < lugkist  | awk '{printf  "%c",$2}' | sed ':a;N;$!ba;s/\n/ /g'
d wPm a ? d ircielmywncaavpahsikv tsnhtencehoBgsa or e de.yoe [Wani@Linux gits]$ 

Looks a little messed. Lets try this sorting according to memory. (Remember assembly instructions in memory?)
[Wani@Linux gits]$ while read line ; do python genie.py $line ; done < lugkist  | sort -k1n | awk '{printf  "%c",$2}' | sed ':a;N;$!ba;s/\n/ /g'
Power overwhelming? Back in my day cheats did not have spaces.[Wani@Linux gits]$ 

GhostInTheShellCode Write-Up Dogecrypt


We were provided with a file encrypted in vim. The hint given was: "Solveable in <5m. Much attack very wamerican-small". wamerican-small is a debian package whose info can be found here. It was evident that brute force had to be applied. Now, to decrypt the files using a key, I found the following perl program online at perlmonks.
use Inline C;

my $password = ;
chomp($password);
my $file = "lol";

open F, $file or die $!;
my $data = do{ local $/;  };
close F;

decode( $data, $password );
print "After:\n$data\n";

__END__
__C__
typedef unsigned int  ULG;

void decode( SV* str, char *passwd ) 
{
    ULG s,t,v,crc_32_tab[256],keys[3],temp;
    STRLEN rawlen;
    int decrypted = 0;
    char *file, *data;
    char *magic = "VimCrypt~01!\0";
#define ROTOR(a) { \
    keys[0] = CRC32(keys[0], a); keys[1] += keys[0] & 0xff; \
    keys[1] = keys[1] * 134775813L + 1; \
    keys[2] = CRC32(keys[2], (int)(keys[1] >> 24)); \
}
#define CRC32(c, b) (crc_32_tab[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8))

    file = (char*)SvPV(str, rawlen);
    if ( rawlen == 0 ) return;  /* we got a null string */
    
    while ( *magic != '\0' ) {
        if ( *(magic++) != *(file++) ) return; /* did not find magic header */
    }
    
    for (t=0; t<256 data-blogger-escaped-for="" data-blogger-escaped-s="" data-blogger-escaped-t="" data-blogger-escaped-v="(v">> 1) ^ ((v & 1) * (ULG)0xedb88320L);
        crc_32_tab[t] = v;
    }
    
    keys[0] = 305419896L; keys[1] = 591751049L; keys[2] = 878082192L;
    
    while (*passwd != '\0') ROTOR(*(passwd++));
    
    data = file;
    while( *file != '\0' ) {
        temp = 0xffff & (keys[2] | 2);
        *file ^= (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
        ROTOR(*(file++));
        decrypted++;
    }

    sv_setpvn( str, data, decrypted ); /* modify the passed SV with decrypt */
}

Applying dictionary attack:
$ while read line ; do echo $line ; echo $line | perl fish.pl  ; done < /usr/share/dict/american-english-small

Grabbing the key, with a little bit of guess-work
[Wani@Linux brute]$ cd out; strings *   | grep -i ctf
GCTf
$BgcTf
CTfJ
ctFe
OcTF
                                                        very much ctf
-CTF
>cTF
NCtf
[Wani@Linux out]$ grep "very much ctf" *
parliament:                                                        very much ctf
[Wani@Linux out]$  cat parliament
After:
The key is: ShibeSuchDictionaryAttacksWow



                                  wow

                                                        very much ctf

                                                                      most key




                            such flag


                                         so much shellcode





                                                        wow

[Wani@Linux out]$