PWNABLE.TW-food_store-分析
看了一段时间,暂时还没有找出洞,自己还是太菜了,考虑到题目的逻辑较复杂,结构体也较多,在这里先记录一下,免得到时候忘了。
程序总共有 7 个功能,在 main 函数中使用一个 switch 来跳转,简单重命名一下如下

recipe
这个函数又有三个功能

add_recipe
重命名一下如下

这里面涉及到 recipe 的单向链表结构体,我猜测其结构如下
struct RECIPE_LIST
{
char recipe_name[24];
struct INGREDIENT *Ingredient[13];
struct RECIPE_LIST *next;
};
其中的 struct INGREDIENT
我猜测其结构为
struct INGREDIENT
{
char name[32];
int price;
int ingredient_left;
};
也就是每一个 recipe 结构体维护其自己的名字和该菜需要使用的食材(ingredient)。而每个 INGREDIENT 结构体则维护自己的名字、价格和所剩的数量。
recipe 链表的头指针处于偏移 0x2050D0 处,IDA 分析时发现这个指针是通过处于偏移 0x2050C8 的基址寻址的,而此处又是 recipe_info 的地址,所以把二者合成一个结构体
struct LIST_HEAD
{
struct Recipe_Info *recipe_info;
// 上面命名不是很合适,我后来改成了 struct ALL_INGREDIENT *all_ingredient
struct RECIPE_LIST **recipe_list_head;
};
这里的 Recipe_Info 结构体(后来改名为 ALL_INGREDIENT)结构我猜测为
struct Recipe_Info // 修改为 ALL_INGREDIENT
{
struct INGREDIENT *ingredient[10];
};
LIST_HEAD 中的 recipe_info(改名为 all_ingredient)维护当前所有的食材和其个数。
说回到函数本身,这是添加食谱(recipe)的函数,我们可以自定义其食材,然后会被链接到食谱链表的尾部。似乎并没有什么洞。
remove_recipe

这里就是根据菜谱的名字来解链特定的菜谱,然后通过 realloc 来对要被删除的食谱进行 free。
show_recipe

这里可以打出所有菜谱的名称和其食材的名称,如果可以做到在链表中保留一个被 free 过的 chunk 的话就有可能通过该函数实现 leak。
Assignment

这个函数主要做的就是给 NPC 吃东西,NPC 会从食谱中随便选一个食物然后要求我们给他吃,如果我们有对应的食物且选择可以提供,那么就可以给 NPC 吃,且可以增加自己的经验(经验到 100 后就会升级),然后增加级别。最后食物会从食物链表中解链,并通过 realloc 进行 free。
这里的食物链表结构我猜测如下
struct FOOD_LIST
{
char name[24];
unsigned int price;
int dummy1;
__int64 energy;
struct FOOD_LIST *next;
struct FOOD_LIST *prev;
};
每一个食物维护自己的名字、价格和能量(能量在后面的 eat 功能中有用),并且通过 next 和 prev 指针维护双向链表。
好像也没有明显的漏洞
show_chief_info

函数很简单,就是输出厨师的信息,可见一个厨师有三个维度的数值
- level:一些对食材的操作对 level 有要求
- power:做食物(do_cooking)需要消耗 power,可以通过 eat 来补充
- money:买食材需要花钱,通过给 NPC 做饭(Assignment)或卖出食物(sell_food)可以获得钱财
do_shopping

这个功能里面也有三个子功能,主要是对食材和食物的操作,可以卖出、购买和制作。
sell_food

卖出指定食物,获得其 price 的钱,然后解链并 free,好像没什么漏洞
buy_ingredint

购买指定个数个食材,每个食材的个数是由位于偏移 0x205080 处的指针来维护的。
make_food

这个函数让我们制作自己的食材(命名有些不恰当,但是我懒得重传图片了,您知晓就行了),每次制作食材都需要花费 100 块钱。
do_cooking
函数比较长,分两段传。


这里就是根据菜谱制作食物,看起来很长但是好像还真没有什么洞..
到这里就功能就分析完了,无奈的确没有发现什么洞,希望明天可以找到洞 PWN 了。