...
Binary analysis (Finding vulnerabilities)
Main
- 当該関数は次のような機能をします。
- 当該関数はsetCandy()関数を呼び出してCandy情報を設定します。
- 当該関数はlogin()関数を呼び出しして使用してアカウント情報を確認します。
- 当該関数は使用者がloginに失敗する場合、次のように動作します。
- 当該関数はloginが失敗の際の使用者にアカウントを生成することか問いかけます。
- 当該関数はaddAccount()関数を利用して新しいアカウントを生成します。
- また、当該関数はloginを3度失敗するとプログラムは終了されます。
- 当該関数は使用者がloginに成功すると、下の機能を利用することができます。
- 向上出力、注文、充電、ログアウト
- gLoginAccount→stateの値が1の場合"orderMenu"、"Account"機能を利用することができます
해당 함수는 다음과 같은 기능을 합니다.- 해당는 함수는 setCandy() 함수를 호출하여 Candy 정보를 설정합니다.
- 해당는 함수는 login() 함수를 호출하여 사용하여 계정정보를 확인합니다.
- 해당는 함수는 사용자가 login에 실패 할 경우 다음과 같이 동작합니다.
- 해당 함수는 login이 실패시 사용자에게 계정을 생성 할 것인지 묻습니다.
- 그리고 해당 함수는 login을 3번 실패하면 프로그램은 종료됩니다.
- 해당는 함수는 사용자가 login에 성공하면 아래 기능들을 이용할 수 있습니다.
- 제고 출력, 주문, 충전, 로그아웃
- gLoginAccount→state 의 값이 1인 경우 "orderMenu", "Account" 기능을 이용 할 수 있습니다.
| Code Block |
|---|
|
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
signed int state; // [rsp+4h] [rbp-Ch]
state = 1;
signal(14, handler);
alarm(0x1Eu);
title();
setCandy();
gOrderCnt = 0;
gLoginFailCnt = 0;
while ( !gLoginAccount )
{
if ( (unsigned int)login() )
{
gLoginFailCnt = 0;
LABEL_14:
while ( state && gLoginAccount )
{
Menu();
printf("Command : ");
switch ( (unsigned int)retNumber(2LL) )
{
case 0u:
state = 0;
break;
case 1u:
printStock();
break;
case 2u:
purchase();
break;
case 3u:
charge();
break;
case 4u:
if ( gLoginAccount->state == 1 )
orderMenu();
break;
case 5u:
if ( gLoginAccount->state == 1 )
Account();
break;
case 9u:
logout(2LL);
break;
default:
goto LABEL_14;
}
}
}
else
{
if ( gLoginFailCnt == 2 )
exit(1);
++gLoginFailCnt;
puts("\nCreate an account?");
puts("0) Yes\n1) No");
if ( !(unsigned int)retNumber(2LL) )
addAccount(3LL);
}
}
return 0LL;
} |
login()
- 当該関数は次のような機能をします。
- 当該関数は使用者からID、Passwordの入力を受けます。
- 当該関数は入力を受けた値を全域変数gAccount[]に存在するかどうか確認します。
- 当該関数は認証に成功すると、該当アカウント情報が保存されたgAccount[]の住所を全域の変数"gLoginAccount"に保存します。
해당 함수는 다음과 같은 기능을 합니다.- 해당 함수는 사용자로 부터 ID,Password를 입력 받습니다.
- 해당 함수는 입력 받은 값을 전역 변수 gAccount[]에 존재하는지 확인합니다.
- 해당 함수는 인증에 성공하면, 해당 계정 정보가 저장된 gAccount[]의 주소를 전역변수 "gLoginAccount" 에 저장합니다.
| Code Block |
|---|
|
signed __int64 login()
{
size_t lenUserInputID; // rbx
size_t lenID; // rax
size_t lenUserInputPW; // rbx
size_t lenPW; // rax
signed int i; // [rsp+Ch] [rbp-34h]
char id[8]; // [rsp+10h] [rbp-30h]
char pw[8]; // [rsp+20h] [rbp-20h]
unsigned __int64 v8; // [rsp+28h] [rbp-18h]
v8 = __readfsqword(0x28u);
memset(id, 0, 8uLL);
memset(pw, 0, 8uLL);
printf("\nEnter your ID.\n> ", 0LL);
UserInput(id, 8LL);
printf("Enter your Password.\n> ", 8LL);
UserInput(pw, 8LL);
for ( i = 0; i <= 2; ++i )
{
if ( gAccount[i].state )
{
lenUserInputID = strlen(id);
if ( lenUserInputID == strlen(gAccount[i].fd->id) )
{
lenID = strlen(gAccount[i].fd->id);
if ( !strncmp(gAccount[i].fd->id, id, lenID) )
{
lenUserInputPW = strlen(pw);
if ( lenUserInputPW == strlen(gAccount[i].fd->pw) )
{
lenPW = strlen(gAccount[i].fd->pw);
if ( !strncmp(gAccount[i].fd->pw, pw, lenPW) )
{
gLoginAccount = (struct ACCOUNT *)(32LL * i + 0x604220);
printf("\nHi, %s", gAccount[i].fd->id);
return 1LL;
}
}
}
}
}
}
return 0LL;
} |
- 해당 함수는 다음과 같은 구조체를 사용합니다.当該関数は次のような構造体を使用します。
| Code Block |
|---|
| language | cpp |
|---|
| title | Struct IDPW, ACCOUNT |
|---|
|
struct IDPW{
long empty[2];
char id[8];
char pw[8];
long state;
char description[88];
};
struct ACCOUNT{
long state;
long number;
struct IDPW *fd;
long bk;
}; |
addAccount()
- 当該関数は次のような機能をします。
- 当該関数は、除隊変数gAccount[]。stateの値が'0'だった場合、次のように動作します。
- 当該関数はmalloc()を使用して128 byteのheap領域を割り当てられます。
- 当該関数は、当該領域の住所をgAccount[i]。fdに保存します。
- 当該関数は、該当領域にID、Password、profile情報を保存します。
해당 함수는 다음과 같은 기능을 합니다.
| Code Block |
|---|
| language | cpp |
|---|
| title | addAccount(unsigned int a1) |
|---|
|
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(128uLL);
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;
} |
purchase
- 当該関数は次のような機能をします。
- 当該関数は、除隊変数gStockCntの値が0の場合、メッセージを出力、当該機能を終了します。
- 当該関数は、除隊変数gStockCntの値が0がない場合、次のような機能をします。
- 当該関数は使用者から購買するキャンディーのコード番号
해당 함수는 다음과 같은 기능을 합니다.
| Code Block |
|---|
| language | cpp |
|---|
| title | purchase() |
|---|
|
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 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 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;
} |
- 다음과 같은 구조체를 사용합니다.次のような構造体を使用します。
| Code Block |
|---|
| language | cpp |
|---|
| title | struct STOCK |
|---|
|
struct STOCK{
char candyName[8];
unsigned int candyNumber;
unsigned int candyPrice;
char *candyDescription;
}; |
setBoard()
- 当該関数は次のような機能をします。
- 当該関数はmalloc()関数を利用して1200 byteのHeap領域を割り当てられます。
- 当該関数は、該当領域に使用者から値を入力を受けて保存します。
해당 함수는 다음과 같은 기능을 합니다.
| Code Block |
|---|
| language | cpp |
|---|
| title | setBoard() |
|---|
|
unsigned __int64 setBoard()
{
unsigned __int64 v0; // ST08_8
v0 = __readfsqword(0x28u);
puts("Please enter a comment for candy.");
board = (__int64)malloc(1200uLL);
UserInput(board, 1200LL);
return __readfsqword(0x28u) ^ v0;
} |
charge
- 当該関数は次のような機能をします。
- 当該関数は使用者から充電する金額の番号は、入力されます。
- 当該関数は、当該金額を
해당 함수는 다음과 같은 기능을 합니다.
- 해당 함수는 사용자로 부터 충전 할 금액의 번호는 입력 받습니다.
- 해당 함수는 해당 금액을 "gLoginAccount→bk" 영역에 더합니다.領域に加えます。
| 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;
} |
Account()
- 当該関数はgLoginAccount->stateの値が1の場合、使用可能です。
- 当該関数は次のような機能をします。
- 当該関数は使用可能な機能のリストを出力します。
- 当該関数は使用者としてから使用する機能の番号を入力を受けて、当該機能を呼び出しています。
- 해당 함수는 gLoginAccount->state의 값이 1인 경우 사용가능합니다.
- 해당 함수는 다음과 같은 기능을 합니다.
- 해당 함수는 사용 가능한 기능 목록을 출력합니다.
- 해당 함수는 사용자로 부터 사용할 기능의 번호를 입력 받아 해당 기능을 호출합니다.
| Code Block |
|---|
| language | cpp |
|---|
| title | Account() |
|---|
|
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;
} |
delAccount()
- 当該関数は次のような機能をします。
- 当該関数は、除隊変数gAccount[]を利用して削除可能なアカウントを出力します。
- 当該関数は使用者から削除する勘定の番号を入力されます。
- 当該関数は使用者が選択したアカウントのstate情報が'3'ある場合、削除を進めます。
해당 함수는 다음과 같은 기능을 합니다.
| Code Block |
|---|
| language | cpp |
|---|
| title | delAccount() |
|---|
|
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;
} |
changePW
- 当該関数は次のような機能をします。
해당 함수는 다음과 같은 기능을 합니다.
| Code Blockcode |
|---|
| language | cpp |
|---|
| title | changePW() |
|---|
|
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;
} |
orderMenu()
- 当該関数はgLoginAccount->stateの値が1の場合、使用可能です。
- 当該関数は次のような機能をします。
- 当該関数は使用可能な機能のリストを出力します。
- 注文リスト、注文リスト追加、注文リストの取り消し、キャンディ注文
- 当該関数は使用者としてから使用する機能の番号を入力を受けて、当該機能を呼び出しています。
- 해당 함수는 gLoginAccount->state의 값이 1인 경우 사용가능합니다.
- 해당 함수는 다음과 같은 기능을 합니다.
- 해당 함수는 사용 가능한 기능 목록을 출력합니다.
- 주문 목록, 주문 목록 추가, 주문 목록 취소, 캔디 주문
- 해당 함수는 사용자로 부터 사용할 기능의 번호를 입력 받아 해당 기능을 호출합니다.
| Code Block |
|---|
| language | cpp |
|---|
| title | orderMenu() |
|---|
|
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;
} |
addToOrderList
- 当該関数は次のような機能をします。
- 当該関数はchoiceCandy()関数を使用して注文するキャンディーの番号を入力されます。
- 当該関数はmalloc()関数を使用して24 byteのheap領域を割り当てられます。
- 当該関数は、該当領域に注文するキャンディーの情報を保存します。
해당 함수는 다음과 같은 기능을 합니다.
| Code Block |
|---|
| language | cpp |
|---|
| title | addToOrderList |
|---|
|
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(24uLL);
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 |
|---|
| language | cpp |
|---|
| title | struct ORDER, CANDIES |
|---|
|
typedef struct ORDER{
char orderCode[8];
unsigned int orderNumber;
char orderCandyName[8];
int candyCode;
};
typedef struct CANDIES {
char candyName[8];
unsigned int orderNumber;
int candyCode;
}; |
orderCancel
- 当該関数は次のような機能をします。
해당 함수는 다음과 같은 기능을 합니다.
| Code Block |
|---|
| language | cpp |
|---|
| title | orderCancel() |
|---|
|
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;
} |
reSort
- 当該関数は次のような機能をします。
- 当該関数はfree()関数を利用してgOrderList
해당 함수는 다음과 같은 기능을 합니다.
- 해당 함수는 free() 함수를 이용해 gOrderList[a1] 영역을 해제합니다.領域を解除します。
| Code Block |
|---|
| language | cpp |
|---|
| title | reSort(unsigned int a1) |
|---|
|
unsigned __int64 __fastcall reSort(unsigned int a1)
{
int i; // [rsp+14h] [rbp-Ch]
unsigned __int64 v3; // [rsp+18h] [rbp-8h]
v3 = __readfsqword(0x28u);
free(gOrderList[a1]);
if ( a1 < gOrderCnt )
{
for ( i = 0; a1 + i < gOrderCnt; ++i )
gOrderList[a1 + i] = gOrderList[a1 + i + 1];
}
gOrderList[gOrderCnt--] = 0LL;
return __readfsqword(0x28u) ^ v3;
} |
orderCandy()
- 当該関数は次のような機能をします。
- 当該関数は使用者からキャンディ注文の進めるかどうかを確認します。
- 当該関数はgetStockNum()関数を使用してgOrderList[]に保存された値がgStock[]に存在するかどうか確認します。
- 当該関数はgOrderList[]に保存された値gStock[]に存在する場合、次のように処理されます。
해당 함수는 다음과 같은 기능을 합니다.
해당 함수는 사용자로 부터 캔디 주문의 진행 여부를 확인합니다.
해당 함수는 getStockNum() 함수를 사용해 gOrderList[]에 저장된 값이 gStock[]에 존재하는지 확인합니다.
해당 함수는 gOrderList[]에 저장된 값 gStock[]에 존재 할 경우 다음과 같이 처리됩니다.- "gStock[]->candyNumber>candyNumber" 에 に"gOrderList[]->orderNumber"의 값을 더하게 됩니다.
해당 함수는 gOrderList[]에 저장된 값 gStock[]에 존재하지 않을 경우 다음과 같이 처리됩니다.
해당 함수는 malloc() 함수를 사용하여 24 byte의 heap 영역을 할당합니다.
해당 함수는 해당 영역에 캔디에 대한 정보를 저장합니다.
그리고 해당 함수는 124 byte의 heap 영역을 할당해서, 해당 영역에 사용자로 부터 입력받은 캔디 정보를 저장합니다.
>orderNumber"の値を加えることになります。- 当該関数はgOrderList[]に保存された値gStock[]に存在しない場合、次のように処理されます。
- 当該関数はmalloc()関数を使用して24 byteのheap領域を割り当てます。
- 当該関数は、該当領域にキャンディに対する情報を保存します。
- キャンディの名前や価格、キャンディの情報が保存されているアドレス値
- また、当該関数は124 byteのheap領域を割り当てて、当該領域に使用者から入力を受けたキャンデー情報を保存します。
- 当該関数はgOrderList[]に保存された値gStock[]にすべて保存した後、gOrderList[]領域を全て解除します。해당 함수는 gOrderList[]에 저장된 값 gStock[]에 모두 저장한 후, gOrderList[] 영역을 모두 해제 합니다.
| Code Block |
|---|
| language | cpp |
|---|
| title | orderCandy() |
|---|
|
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) )
{
for ( i = 0; i < gOrderCnt; ++i )
{
num = getStockNum(i);
if ( num )
{
gStock[num - 1]->candyNumber += gOrderList[i]->orderNumber;
}
else if ( (unsigned int)gStockCnt > 4 )
{
puts("The warehouse is full. Your new order can not be completed.");
}
else
{
puts("\nEnter information about newly added candy.");
dest = (struct STOCK *)malloc(24uLL);
strncpy(dest->candyName, gOrderList[i]->orderCandyName, 8uLL);
dest->candyNumber = gOrderList[i]->orderNumber;
printf("Enter the price of %s candy.\n", dest);
dest->candyPrice = retNumber(5LL);
printf("Enter a description of the %s candy.\n", dest);
dest->candyDescription = (char *)malloc(124uLL);
UserInput(dest->candyDescription, 124LL);
gStock[gStockCnt++] = dest;
}
}
while ( gOrderCnt )
{
free(gOrderList[gOrderCnt - 1]);
gOrderList[gOrderCnt-- - 1] = 0LL;
}
}
}
else
{
puts("You have never ordered a product.");
}
return __readfsqword(0x28u) ^ v4;
} |
...