...
Code Block |
---|
unsigned __int64 purchase() { unsigned int v0; // ST00_4 unsigned int candyInfo[2]; // [rsp+0h] [rbp-10h] unsigned __int64 v3; // [rsp+8h] [rbp-8h] v3 = __readfsqword(0x28u); if ( gStockCnt ) { puts("Please enter the code number of the candy to be purchased."); candyInfo[0] = retNumber(3LL); if ( candyInfo[0] < gStockCnt ) { puts("Please enter the number of the candy to purchase."); candyInfo[1] = retNumber(3LL); if ( gStock[candyInfo[0]]->candyNumber < candyInfo[1] ) { if ( gStock[candyInfo[0]]->candyNumber < candyInfo[1] ) puts("There is not enough stock."); } else if ( candyInfo[1] * gStock[candyInfo[0]]->candyPrice > gLoginAccount->bk ) { printf( "You do not have enough "You do not have enough money.(%ld)\n", candyInfo[1] * gStock[candyInfo[0]]->candyPrice, *(_QWORD *)candyInfo); } else { gStock[candyInfo[0]]->candyNumber -= candyInfo[1]; if ( !gStock[candyInfo[0]]->candyNumber ) { printf( "Thank you for your "Thank you for your purchase.(%ld)\n", candyInfo[1] * gStock[candyInfo[0]]->candyPrice, *(_QWORD *)candyInfo); reSortStock(v0); setBoard(); } } } } else { puts("We have not any candy."); } return __readfsqword(0x28u) ^ v3; } |
.init_array
- 다음과 같이 .init
Code Block | ||
---|---|---|
| ||
lazenca0x0@ubuntu:~/Documents/CTF/SECCON2017$ gdb -q ./L*
Reading symbols from ./Lazenca.0x0...(no debugging symbols found)...done.
gdb-peda$ readelf
.interp = 0x400238
.note.ABI-tag = 0x400254
.note.gnu.build-id = 0x400274
.gnu.hash = 0x400298
.dynsym = 0x4002b8
.dynstr = 0x4004c8
.gnu.version = 0x400580
.gnu.version_r = 0x4005b0
.rela.dyn = 0x4005e0
.rela.plt = 0x4005f8
.init = 0x4007d8
.plt = 0x400800
.plt.got = 0x400950
.text = 0x400960
.fini = 0x4029c4
.rodata = 0x4029d0
.eh_frame_hdr = 0x40376c
.eh_frame = 0x403888
.init_array = 0x603e08
.fini_array = 0x603e18
.jcr = 0x603e20
.dynamic = 0x603e28
.got = 0x603ff8
.got.plt = 0x604000
.data = 0x6040b8
.bss = 0x6040e0
gdb-peda$ x/2gx 0x603e08
0x603e08: 0x0000000000400a30 0x000000000040266b
gdb-peda$ x/5i 0x000000000040266b
0x40266b: push rbp
0x40266c: mov rbp,rsp
0x40266f: sub rsp,0x10
0x402673: mov rax,QWORD PTR fs:0x28
0x40267c: mov QWORD PTR [rbp-0x8],rax
gdb-peda$ |
addAdmin
- 해당 함수에서는 다음과 같은 Struct를 사용합니다.
Code Block | ||
---|---|---|
| ||
struct IDPW{
long empty[2];
char id[IDPWMAX];
char pw[IDPWMAX];
long state;
char description[88];
};
struct ACCOUNT{
long state;
long number;
struct IDPW *fd;
long bk;
}; |
- 해당 함수는 다음과 같은 기능을 합니다.
- 전역 변수 gAccount[0]에 다음과 같은 값을 저장 합니다.
- state = 1
- number = 1
- fd→id = "Admin"
- fd→pw = "admin"
- state 변수에 1을 저장하고 있으며, 해당 계정으로 "orderMenu", "Account" 기능을 이용 할 수 있습니다.
- 전역 변수 gAccount[0]에 다음과 같은 값을 저장 합니다.
Code Block | ||||
---|---|---|---|---|
| ||||
unsigned __int64 addAdmin()
{
unsigned __int64 v0; // ST08_8
v0 = __readfsqword(0x28u);
gAccount[0].state = 1LL;
gAccount[0].number = 1LL;
gAccount[0].fd = (struct IDPW *)malloc(0x80uLL);
gAccount[0].bk = 880LL;
strncpy(gAccount[0].fd->id, "Admin", 8uLL);
strncpy(gAccount[0].fd->pw, "admin", 8uLL);
strncpy(gAccount[0].fd->description, "I'm Lazenca.0x0\nWebsite is \"https://www.lazenca.net/\"", 0x58uLL);
return __readfsqword(0x28u) ^ v0;
} |
Account
- 해당 함수는 다음과 같은 기능을 합니다.
charge
Code Block |
---|
unsigned __int64 charge()
{
unsigned int chargeInfo[2]; // [rsp+0h] [rbp-10h]
unsigned __int64 v2; // [rsp+8h] [rbp-8h]
v2 = __readfsqword(0x28u);
chargeInfo[0] = 0;
puts("Please select the amount to charge.");
puts("0) 1");
puts("1) 10");
puts("2) 100");
puts("3) 1000");
puts("4) 10000");
puts("5) 100000");
chargeInfo[1] = retNumber(2LL);
switch ( chargeInfo[1] )
{
case 0u:
chargeInfo[0] = 1;
break;
case 1u:
chargeInfo[0] = 10;
break;
case 2u:
chargeInfo[0] = 100;
break;
case 3u:
chargeInfo[0] = 1000;
break;
case 4u:
chargeInfo[0] = 10000;
break;
case 5u:
chargeInfo[0] = 100000;
break;
default:
break;
}
gLoginAccount->bk += chargeInfo[0];
printf("%ld yen charged.\n", chargeInfo[0], *(_QWORD *)chargeInfo);
return __readfsqword(0x28u) ^ v2;
} |
.init_array
- 다음과 같이 .init
Code Block | ||
---|---|---|
| ||
lazenca0x0@ubuntu:~/Documents/CTF/SECCON2017$ gdb -q ./L*
Reading symbols from ./Lazenca.0x0...(no debugging symbols found)...done.
gdb-peda$ readelf
.interp = 0x400238
.note.ABI-tag = 0x400254
.note.gnu.build-id = 0x400274
.gnu.hash = 0x400298
.dynsym = 0x4002b8
.dynstr = 0x4004c8
.gnu.version = 0x400580
.gnu.version_r = 0x4005b0
.rela.dyn = 0x4005e0
.rela.plt = 0x4005f8
.init = 0x4007d8
.plt = 0x400800
.plt.got = 0x400950
.text = 0x400960
.fini = 0x4029c4
.rodata = 0x4029d0
.eh_frame_hdr = 0x40376c
.eh_frame = 0x403888
.init_array = 0x603e08
.fini_array = 0x603e18
.jcr = 0x603e20
.dynamic = 0x603e28
.got = 0x603ff8
.got.plt = 0x604000
.data = 0x6040b8
.bss = 0x6040e0
gdb-peda$ x/2gx 0x603e08
0x603e08: 0x0000000000400a30 0x000000000040266b
gdb-peda$ x/5i 0x000000000040266b
0x40266b: push rbp
0x40266c: mov rbp,rsp
0x40266f: sub rsp,0x10
0x402673: mov rax,QWORD PTR fs:0x28
0x40267c: mov QWORD PTR [rbp-0x8],rax
gdb-peda$ |
addAdmin
- 해당 함수에서는 다음과 같은 Struct를 사용합니다.
Code Block | ||
---|---|---|
| ||
struct IDPW{
long empty[2];
char id[IDPWMAX];
char pw[IDPWMAX];
long state;
char description[88];
};
struct ACCOUNT{
long state;
long number;
struct IDPW *fd;
long bk;
}; |
해당 함수는 다음과 같은 기능을 합니다.
전역 변수 gAccount[0]에 다음과 같은 값을 저장 합니다.
state = 1
number = 1
fd→id = "Admin"
fd→pw = "admin"
state 변수에 1을 저장하고 있으며, 해당 계정으로 "orderMenu", "Account" 기능을 이용 할 수 있습니다.
Code Block | ||||
---|---|---|---|---|
| ||||
unsigned __int64 addAdmin()
{
unsigned __int64 v0; // ST08_8
v0 = __readfsqword(0x28u);
gAccount[0].state = 1LL;
gAccount[0].number = 1LL;
gAccount[0].fd = (struct IDPW *)malloc(0x80uLL);
gAccount[0].bk = 880LL;
strncpy(gAccount[0].fd->id, "Admin", 8uLL);
strncpy(gAccount[0].fd->pw, "admin", 8uLL);
strncpy(gAccount[0].fd->description, "I'm Lazenca.0x0\nWebsite is \"https://www.lazenca.net/\"", 0x58uLL);
return __readfsqword(0x28u) ^ v0;
} |
Account
- 해당 함수는 다음과 같은 기능을 합니다.
Code Block |
---|
unsigned __int64 Account()
{
int tmp; // eax
signed int i; // [rsp+8h] [rbp-58h]
signed int control; // [rsp+Ch] [rbp-54h]
char funcList[3][22]; // [rsp+10h] [rbp-50h]
unsigned __int64 v5; // [rsp+58h] [rbp-8h]
v5 = __readfsqword(0x28u);
control = 1;
strcpy((char *)funcList, "Delete account");
*(_DWORD *)&funcList[0][16] = 0;
*(_WORD *)&funcList[0][20] = 0;
strcpy(funcList[1], "Change password");
*(_DWORD *)&funcList[1][16] = 0;
*(_WORD *)&funcList[1][20] = 0;
*(_OWORD *)&funcList[2][0] = (unsigned __int64)'tixE';
*(_DWORD *)&funcList[2][16] = 0;
*(_WORD *)&funcList[2][20] = 0;
while ( control )
{
puts("\nAccount.");
for ( i = 0; i <= 2; ++i )
printf("%d) %s\n", (unsigned int)(i + 1), funcList[i]);
printf("Command : ");
tmp = retNumber(2LL);
switch ( tmp )
{
case 2:
changePW();
break;
case 3:
control = 0;
break;
case 1:
delAccount();
break;
}
}
return __readfsqword(0x28u) ^ v5;
} |
addAccount
Code Block |
---|
unsigned __int64 __fastcall addAccount(unsigned int a1)
{
unsigned int i; // [rsp+10h] [rbp-10h]
signed int empty; // [rsp+14h] [rbp-Ch]
unsigned __int64 v4; // [rsp+18h] [rbp-8h]
v4 = __readfsqword(0x28u);
empty = 1;
for ( i = 0; i <= 2 && empty; ++i )
{
if ( !gAccount[i].state )
{
empty = 0;
gAccount[i].state = a1;
gAccount[i].number = i + 1;
gAccount[i].fd = (struct IDPW *)malloc(0x80uLL);
gAccount[i].fd->state = 1LL;
puts("\nEnter your New ID.");
UserInput(gAccount[i].fd->id, 8LL);
puts("Enter your New Password.");
UserInput(gAccount[i].fd->pw, 8LL);
puts("Enter your profile.");
UserInput(gAccount[i].fd->description, 88LL);
gAccount[i].bk = 10000LL;
}
}
if ( empty )
puts("Could not add user.");
return __readfsqword(0x28u) ^ v4;
} |
delAccount
Code Block |
---|
unsigned __int64 delAccount()
{
unsigned int i; // [rsp+8h] [rbp-18h]
unsigned int num; // [rsp+Ch] [rbp-14h] MAPDST
unsigned __int64 v4; // [rsp+18h] [rbp-8h]
v4 = __readfsqword(0x28u);
puts("\nAccount list");
for ( i = 0; i <= 2; ++i )
{
if ( gAccount[i].state )
printf("%d) %s\n", gAccount[i].number, gAccount[i].fd->id);
}
puts("\nPlease enter the number of the account you want to delete");
num = retNumber(2LL);
if ( num && num <= 3 )
{
if ( gAccount[--num].state == 3 )
{
gAccount[num].state = 0LL;
gAccount[num].fd->state = 0LL;
printf("The account(%s) has been deleted.\n", gAccount[num].fd->id);
memset(gAccount[num].fd, 0, 0x80uLL);
free(gAccount[num].fd);
gAccount[num].fd = (struct IDPW *)((char *)gAccount[num].fd - 16);
}
else
{
puts("You can not delete the account.");
}
}
return __readfsqword(0x28u) ^ v4;
} |
Code Block |
---|
unsigned __int64 changePW()
{
unsigned int i; // [rsp+8h] [rbp-18h]
unsigned int num; // [rsp+Ch] [rbp-14h] MAPDST
unsigned __int64 v4; // [rsp+18h] [rbp-8h]
v4 = __readfsqword(0x28u);
puts("\nAccount list");
for ( i = 0; i <= 2; ++i )
{
if ( gAccount[i].state )
printf("%ld) %s\n", gAccount[i].number, gAccount[i].fd->id);
}
puts("\nPlease enter the number of the account you want to change PW");
num = retNumber(2LL);
if ( num )
{
if ( num <= 3 )
{
if ( gAccount[--num].fd )
{
if ( gAccount[num].fd->state )
{
puts("Enter your New Password.");
UserInput(gAccount[num].fd->pw, 8LL);
}
}
}
}
return __readfsqword(0x28u) ^ v4;
} |
Code Block |
---|
unsigned __int64 orderMenu()
{
signed int i; // [rsp+8h] [rbp-88h]
unsigned int control; // [rsp+Ch] [rbp-84h]
char funcList[5][22]; // [rsp+10h] [rbp-80h]
unsigned __int64 v4; // [rsp+88h] [rbp-8h]
v4 = __readfsqword(0x28u);
control = 1;
strcpy((char *)funcList, "Order List");
*(_DWORD *)&funcList[0][16] = 0;
*(_WORD *)&funcList[0][20] = 0;
strcpy(funcList[1], "Add to Order List");
*(_WORD *)&funcList[1][20] = 0;
*(_QWORD *)&funcList[2][0] = 'o lecnaC';
*(_QWORD *)&funcList[2][8] = 'o s���en';
*(_DWORD *)&funcList[2][16] = 'redr';
*(_WORD *)&funcList[2][20] = '.';
strcpy(funcList[3], "Order candy");
*(_DWORD *)&funcList[3][16] = 0;
*(_WORD *)&funcList[3][20] = 0;
*(_OWORD *)&funcList[4][0] = (unsigned __int64)'tixE';
*(_DWORD *)&funcList[4][16] = 0;
*(_WORD *)&funcList[4][20] = 0;
LABEL_11:
while ( control )
{
puts("\nOrder candy.");
for ( i = 0; i <= 4; ++i )
printf("%d) %s\n", (unsigned int)(i + 1), funcList[i]);
printf("Command : ");
switch ( (unsigned int)retNumber(2LL) )
{
case 1u:
orderList();
break;
case 2u:
addToOrderList();
break;
case 3u:
orderCancel();
break;
case 4u:
orderCandy();
break;
case 5u:
control = 0;
break;
default:
goto LABEL_11;
}
}
return __readfsqword(0x28u) ^ v4;
} |
Code Block |
---|
unsigned __int64 orderList()
{
unsigned int i; // [rsp+4h] [rbp-Ch]
unsigned __int64 v2; // [rsp+8h] [rbp-8h]
v2 = __readfsqword(0x28u);
if ( gOrderCnt )
{
puts("\n=*= Order list =*=");
for ( i = 0; i < gOrderCnt; ++i )
{
printf("\nOrder code : %s\n", gOrderList[i]);
printf("Order count : %d\n", gOrderList[i]->orderNumber);
printf("Order candy : %s\n", gOrderList[i]->orderCandyName);
printf("Candy code : %d\n", (unsigned int)gOrderList[i]->candyCode);
}
}
else
{
puts("You have never ordered a product.");
}
return __readfsqword(0x28u) ^ v2;
} |
Code Block | ||||
---|---|---|---|---|
| ||||
unsigned __int64 addToOrderList()
{
struct ORDER *newOrder; // ST08_8
unsigned int tmp; // eax
unsigned int candyNum; // [rsp+4h] [rbp-1Ch]
char strOrdNum[8]; // [rsp+10h] [rbp-10h]
unsigned __int64 v5; // [rsp+18h] [rbp-8h]
v5 = __readfsqword(0x28u);
if ( (unsigned int)gOrderCnt > 9 )
{
puts("You can not order candy anymore.");
}
else
{
candyNum = choiceCandy();
if ( candyNum > 9 )
{
puts("Please enter a number between 0 and 9");
}
else
{
newOrder = (struct ORDER *)malloc(0x18uLL);
tmp = getOrderNum();
sprintf(strOrdNum, "%d", tmp);
strncpy(newOrder->orderCode, strOrdNum, 1uLL);
newOrder->orderNumber = gCandies[candyNum]->orderNumber;
strncpy(newOrder->orderCandyName, gCandies[candyNum]->candyName, 8uLL);
newOrder->candyCode = gCandies[candyNum]->candyCode;
gOrderList[gOrderCnt++] = newOrder;
orderList();
}
}
return __readfsqword(0x28u) ^ v5;
} |
Code Block |
---|
unsigned __int64 orderCancel()
{
unsigned int i; // [rsp+Ch] [rbp-44h]
int j; // [rsp+Ch] [rbp-44h]
int orderCnt; // [rsp+10h] [rbp-40h]
unsigned int canNum; // [rsp+1Ch] [rbp-34h]
int cancelableList[10]; // [rsp+20h] [rbp-30h]
unsigned __int64 v6; // [rsp+48h] [rbp-8h]
v6 = __readfsqword(0x28u);
orderCnt = 0;
if ( gOrderCnt )
{
for ( i = 0; i < gOrderCnt; ++i )
{
if ( (unsigned int)checkCancel(i) )
{
cancelableList[orderCnt++] = i;
printf("\n=*= Cancelable order (Order number : %d) =*=\n", i);
printf("Order code: %s\n", gOrderList[i]);
printf("Order count : %d\n", gOrderList[i]->orderNumber);
printf("Order candy : %s\n", gOrderList[i]->orderCandyName);
printf("Candy code: %d\n", (unsigned int)gOrderList[i]->candyCode);
}
}
if ( orderCnt )
{
canNum = retNumber(2LL);
for ( j = 0; j < orderCnt; ++j )
{
if ( cancelableList[j] == canNum )
reSort(canNum);
}
}
}
else
{
puts("You have never ordered a product.");
}
return __readfsqword(0x28u) ^ v6;
} |
Code Block |
---|
unsigned __int64 orderCandy()
{
struct STOCK *dest; // ST10_8
unsigned int i; // [rsp+4h] [rbp-1Ch]
int num; // [rsp+Ch] [rbp-14h]
unsigned __int64 v4; // [rsp+18h] [rbp-8h]
v4 = __readfsqword(0x28u);
if ( gOrderCnt )
{
orderList();
puts("\nWould you like to order these candies?");
puts("0) Yes, 1) No");
if ( !(unsigned int)retNumber(2LL) )
{
|
Code Block |
unsigned __int64 Account() { int tmp; // eax signed int i; // [rsp+8h] [rbp-58h] signed int control; // [rsp+Ch] [rbp-54h] char funcList[3][22]; // [rsp+10h] [rbp-50h] unsigned __int64 v5; // [rsp+58h] [rbp-8h] v5 = __readfsqword(0x28u); control = 1; strcpy((char *)funcList, "Delete account"); *(_DWORD *)&funcList[0][16] = 0; *(_WORD *)&funcList[0][20] = 0; strcpy(funcList[1], "Change password"); *(_DWORD *)&funcList[1][16] = 0; *(_WORD *)&funcList[1][20] = 0; *(_OWORD *)&funcList[2][0] = (unsigned __int64)'tixE'; *(_DWORD *)&funcList[2][16] = 0; *(_WORD *)&funcList[2][20] = 0; while ( control ) { puts("\nAccount."); for ( i = 0; i <= 2gOrderCnt; ++i ) printf("%d) %s\n", (unsigned int)(i + 1), funcList[i]); printf("Command : "); { num = getStockNum(i); tmp =if retNumber(2LL num ); switch ( tmp ){ { gStock[num case 2:- 1]->candyNumber += gOrderList[i]->orderNumber; changePW();} break; else if ( (unsigned int)gStockCnt > case4 3:) { control = 0; puts("The warehouse break; is full. Your new order can case 1:not be completed."); delAccount();} break;else } } return __readfsqword(0x28u) ^ v5; } |
delAccount
Code Block |
---|
unsigned __int64 delAccount() { unsigned int i; // [rsp+8h] [rbp-18h] unsigned int num; // [rsp+Ch] [rbp-14h] MAPDST unsigned __int64 v4; // [rsp+18h] [rbp-8h] v4 = __readfsqword(0x28u); puts("\nAccount list"); for ( i = 0; i <= 2; ++i ) { if ( gAccount[i].state ){ puts("\nEnter information about newly added candy."); dest = (struct STOCK *)malloc(0x18uLL); strncpy(dest->candyName, gOrderList[i]->orderCandyName, 8uLL); dest->candyNumber = gOrderList[i]->orderNumber; printf("Enter the price of %s candy.\n", dest); printf("%d) %s\n", gAccount[i].number, gAccount[i].fd->id dest->candyPrice = retNumber(5LL); } putsprintf("\nPleaseEnter entera thedescription number of the account you want to delete"%s candy.\n", dest); num = retNumber(2LL); if ( num && numdest->candyDescription <= 3 ) {(char *)malloc(0x7CuLL); if ( gAccount[--num].state == 3 ) UserInput(dest->candyDescription, 124LL); { gAccountgStock[numgStockCnt++].state = 0LLdest; gAccount[num].fd->state = 0LL;} printf("The account(%s) has been deleted.\n", gAccount[num].fd->id); memset(gAccount[num].fd, 0, 0x80uLL);} while ( gOrderCnt ) { free(gAccount[num].fdgOrderList[gOrderCnt - 1]); gAccount[num].fd = (struct IDPW *)((char *)gAccount[num].fd - 16);gOrderList[gOrderCnt-- - 1] = 0LL; } } } else { puts("You canhave notnever deleteordered thea accountproduct."); } } return __readfsqword(0x28u) ^ v4; } |
...