PWNABLE.TW-food_store-分析

Posted on Jun 10, 2021

看了一段时间,暂时还没有找出洞,自己还是太菜了,考虑到题目的逻辑较复杂,结构体也较多,在这里先记录一下,免得到时候忘了。

程序总共有 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 了。