I’ve created a custom shopping cart system. Can you get the flag?
nc 164.90.193.27 50009
shop.elf
We get the binary shop_8059c17ac3.elf
so lets open up decompiler and
play with it a bit.
The programm opens port 50009
and wait for a connection:
$ nc localhost 50009
Welcome to our password storage!
1> Create New Session
2> Work With Existing Session
3> Exit
1
90495438b91bc707910561255b74c94c
1> Add new item to shopping cart
2> Delete item from shopping cart
3> Reload shopping cart
4> Print shopping cart
5> Change amount
6> Enter coupon to get gift
7> Proceed
8> Logout
1
Enter item name: My Item
Enter item cost: 10
Enter item amount: 1
1> Add new item to shopping cart
2> Delete item from shopping cart
3> Reload shopping cart
4> Print shopping cart
5> Change amount
6> Enter coupon to get gift
7> Proceed
8> Logout
4
Total: 10$
Item:
Name: My Item
Price: 10$
Amount: 1
1> Add new item to shopping cart
2> Delete item from shopping cart
3> Reload shopping cart
4> Print shopping cart
5> Change amount
6> Enter coupon to get gift
7> Proceed
8> Logout
What I've got during one hour:
Item
and Cart
We'll get to the MUST_BE_NON_ZERO
field later
7> Proceed
of the second menu.
int __fastcall proceed(unsigned int fd, Cart *items, const char *session) // 4025C4
{
char command[1024]; // [rsp+20h] [rbp-420h] BYREF
Item *ptr; // [rsp+420h] [rbp-20h]
Item *item; // [rsp+428h] [rbp-18h]
char *secret; // [rsp+430h] [rbp-10h]
int empty_item; // [rsp+438h] [rbp-8h]
int i; // [rsp+43Ch] [rbp-4h]
if ( items->MUST_BE_NON_ZERO )
{
empty_item = find_empty_item(items);
if ( empty_item != -1 )
{
secret = getenv("SECRET");
item = (Item *)malloc(0x10uLL);
item->name = strdup(secret);
item->cost = 1290;
item->amount = 331;
items->items[empty_item] = item;
}
}
print_cart(fd, items);
items->sum_cost = 0LL;
items->MUST_BE_NON_ZERO = 0LL;
for ( i = 0; i <= 31; ++i )
{
ptr = items->items[i];
if ( ptr )
{
free(ptr->name);
free(ptr);
items->items[i] = 0LL;
}
}
sprintf(command, "rm -rf %s", session);
return system(command);
}
int __fastcall find_empty_item(Cart *a1)
{
int i; // [rsp+14h] [rbp-4h]
for ( i = 0; i <= 31; ++i )
{
if ( !a1->items[i] )
return i;
}
return 4294967295; // -1
}
So obviously we need to set MUST_BE_NON_ZERO
to non zero value and
then type Proceed
. Mention that Cart *items
is created when client
establish connection, and all operations will be performed
precisely with this instsance.
5> Change amount
:
1|
2|
3|
4|
5|
6|
7|
8|
9|
10|
11|
12|
13|
14|
15|
*16|
17|
18|
19|
20|
21|
22|
23|
24|
25|
26|
27|
28|
29|
void __fastcall change_amount(int fd, Cart *items, const char *session) // 4021EC
{
char item_name[256]; // [rsp+20h] [rbp-120h] BYREF
Item *ptr; // [rsp+120h] [rbp-20h]
int item_or_empty; // [rsp+12Ch] [rbp-14h]
char *path; // [rsp+130h] [rbp-10h]
int path_length; // [rsp+13Ch] [rbp-4h]
send(fd, "Enter item name: ", 0x11uLL, 0);
read_line(fd, item_name, 128);
path_length = snprintf(0LL, 0LL, "%s/%s", session, item_name);
path = (char *)malloc(path_length + 1);
sprintf(path, "%s/%s", session, item_name);
if ( contains_item(items, item_name) )
{
item_or_empty = find_item_or_empty(items, item_name, path);
if ( item_or_empty == -1 )
send(fd, "No such item!\n", 0xEuLL, 0);
ptr = items->items[item_or_empty];
if ( ptr )
{
free(ptr->name);
free(ptr);
}
ptr = input_item(fd, item_name);
items->items[item_or_empty] = ptr;
}
free(path);
}
find_item_or_empty
:
__int64 __fastcall find_item_or_empty(Cart *items, const char *item_name, const char *path) // 401DDF
{
unsigned int empty_item; // [rsp+2Ch] [rbp-14h]
Item *v6; // [rsp+30h] [rbp-10h]
int i; // [rsp+38h] [rbp-8h]
unsigned int v8; // [rsp+3Ch] [rbp-4h]
v8 = -1;
for ( i = 0; i <= 31; ++i )
{
v6 = items->items[i];
if ( v6 && !strcmp(v6->name, item_name) )
{
v8 = i;
break;
}
}
if ( access(path, 0) == -1 )
return 0xFFFFFFFELL; // -2
if ( v8 != -1 )
return v8;
empty_item = find_empty_item(items);
if ( empty_item == -1 )
return 0xFFFFFFFFLL; // -1
else
return empty_item;
}
contains_item
:
int __fastcall contains_item(Cart *items, const char *item_name)
{
Item *v3; // [rsp+10h] [rbp-10h]
int i; // [rsp+1Ch] [rbp-4h]
for ( i = 0; i <= 31; ++i )
{
v3 = items->items[i];
if ( v3 && !strcmp(v3->name, item_name) )
return 1;
}
return 0;
}
The contains_item
function only checks if the items is
presented in the cart, but find_item_or_empty
try to
access the corresponding file, and if it's, for
example, deleted returns -2
.
So now we just want the call to find_item_or_empty
on critical
line
in change_amount
to return -2
, and the items->items[-2]
is exactly
NEED_TO_BE_NON_ZERO
field, which then sets to non zero value.
1
) and then create item(1
)
2
) created in 1.
, reload cart(3
) and then delete this item(2
)
5
) whaterever you want and then proceed(7
)