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!

Không có nhận xét nào:

Đăng nhận xét