Skip to main content

HGAME ShellcodeMaster wp

这道题给我幼小的心灵造成了极大的震撼,我是第一次自己写shellcode(哎,从hgame开始到现在,基本每道题我都是第一次做,现学现做,不是靠着ysyx项目积累的一点基础恐怕我早就放弃了),但是这道题目写的时间并不长(相比前几道堆题来说)

首先分析反汇编

这道题目对于写shellcode有三个限制,每一个限制都是要我命

  • 1.沙盒禁用execve和execvat
  • 2.空间只有0x16
  • 3.最后将shellcode的区域的读写权限关掉了

第一个,导致我只能用orw,但是orw需要的空间比较大,0x16必然是不可能的,其实我这里不太会操作,搜了一下google,竟然搜到了hgame 2023的这类题(我不是故意的🤪),思路的话就是扩展空间,用一个小shellcode用read系统调用加载一个大的shellcode,但是,2024的这个没有那么简单,它最后对这个空间设置了权限,一个很自然的想法就是在这0x16的空间,先用mprotect解开权限,再用read申请大空间加载一个大shellcode,可以与文字提示相印证“I heard that a super shellcode master can accomplish 2 functions with 0x16 bytes shellcode”,2 function是不是就是指的这两个呢,我猜估计是,于是,接下来就是这道题最麻烦的地方了,在0x16的空间写下mprotect和read两个系统调用(并且不能有涉及栈的操作,因为所有寄存器会在最后被设置成0x2333,除了跳转的r15是0x2333000)

在这个过程中,我经历了从0x19到0x18再到0x17最后成功0x16的过程(太感人了🥲)

我将讲解我的几个优化点

首先是mprotect的syscall

函数原型int mprotect(void *addr, size_t len, int prot); 主要是针对于len的优化,也就是用rsi现有的值,第九第十行特别占空间,每条都是4字节指令,但是我是真的不会优化这几条指令

函数原型ssize_t read(int fd, void *buf, size_t count); 主要的优化 是第12行,xchg指令,在交换eax和edx的值时只有一字节长度(我从0x17到0x16就靠的是他),edx传递的是大小,不知为什么,第一个syscall的返回值是一个负数,这就导致了eax是一个巨大的数(由于size_t是个unsigned),第二个优化是用e的寄存器而不是r,e的普遍会更短。上述两段加起来正好0x16字节。

之后就很简单了,只需要将flag字符串写到上面,空隙用0填充,最后加上orw的shellcode即可(注意,这段shellcode是不能操作栈的,由于不能操作栈,网上没有这样的,还是我亲自指挥gpd写的hhh)

exp