emem其实我是顺便记录一下我调试的命令哈
pwngdb
这个工具调试对堆有好处然后gdb-peda对输出反编译的代码观察有好处所以你们可以选择反正我是都有~~
babyrop 是一道基础的pwn题简单的栈溢出
这里我就简单的用这个程序来练一下我的调试技术
main函数
int __cdecl main()
{
int buf; // [esp+4h] [ebp-14h]
char v2; // [esp+Bh] [ebp-Dh]
int fd; // [esp+Ch] [ebp-Ch]
sub_80486BB();
fd = open("/dev/urandom", 0);
if ( fd > 0 )
read(fd, &buf, 4u);
v2 = sub_804871F(buf);
sub_80487D0(v2);
return 0;
}
emem这个随机数很安全而且只能进入一次然后就别想爆破了~
int __cdecl sub_804871F(int a1)
{
size_t v1; // eax
char s; // [esp+Ch] [ebp-4Ch]
char buf[7]; // [esp+2Ch] [ebp-2Ch]
unsigned __int8 v5; // [esp+33h] [ebp-25h]
ssize_t v6; // [esp+4Ch] [ebp-Ch]
memset(&s, 0, 0x20u);
memset(buf, 0, 0x20u);
sprintf(&s, "%ld", a1);
v6 = read(0, buf, 0x20u);
buf[v6 - 1] = 0;
v1 = strlen(buf);
if ( strncmp(buf, &s, v1) )
exit(0);
write(1, "Correct\n", 8u);
return v5;
}
这里就有00截断的问题绕过随机数了
ECX: 0x2c (',')
EDX: 0x0
ESI: 0xf7f9e000 --> 0x1b1db0
EDI: 0xf7f9e000 --> 0x1b1db0
EBP: 0xff83a998 --> 0xff83a9c8 --> 0x0
ESP: 0xff83a930 --> 0xff83a96c --> 0x80808000
EIP: 0x804879e (call 0x8048598)
EFLAGS: 0x296 (carry PARITY ADJUST zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x8048799: push eax
0x804879a: lea eax,[ebp-0x2c]
0x804879d: push eax
=> 0x804879e: call 0x8048598
0x80487a3: add esp,0x10
0x80487a6: test eax,eax
0x80487a8: jne 0x80487c4
0x80487aa: sub esp,0x4
Guessed arguments:
arg[0]: 0xff83a96c --> 0x80808000
arg[1]: 0xff83a94c ("-136050305")
arg[2]: 0x0
[------------------------------------stack-------------------------------------]
0000| 0xff83a930 --> 0xff83a96c --> 0x80808000
0004| 0xff83a934 --> 0xff
这里可以清楚看见匹配函数的参数
EAX: 0xffffff80
EBX: 0x0
ECX: 0x804892e ("Correct\n")
EDX: 0x8
ESI: 0xf7f9e000 --> 0x1b1db0
EDI: 0xf7f9e000 --> 0x1b1db0
EBP: 0xff83a9c8 --> 0x0
ESP: 0xff83a9a0 --> 0xffffff80
EIP: 0x8048884 (call 0x80487d0)
EFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x804887c: movsx eax,BYTE PTR [ebp-0xd]
0x8048880: sub esp,0xc
0x8048883: push eax
=> 0x8048884: call 0x80487d0
0x8048889: add esp,0x10
0x804888c: mov eax,0x0
0x8048891: mov ecx,DWORD PTR [ebp-0x4]
0x8048894: leave
Guessed arguments:
arg[0]: 0xffffff80
[------------------------------------stack-------------------------------------]
0000| 0xff83a9a0 --> 0xffffff80
0004| 0xff83a9a4 --> 0xff83a9b4 --> 0xf7e4097f (<_IO_vfscanf_internal+22879>: cli)
0008| 0xff83a9a8 --> 0x4
0012| 0xff83a9ac --> 0x804883b (sub esp,0x8)
0016| 0xff83a9b0 --> 0x1
0020| 0xff83a9b4 --> 0xf7e4097f (<_IO_vfscanf_internal+22879>: cli)
0024| 0xff83a9b8 --> 0x8083aa7c
0028| 0xff83a9bc --> 0x3
这里就进入了可以溢出的函数了这里可以输入的参数变成了0xffffff80 我也思考过是不是整形的溢出或者其他一类这样的所以但是有点晚了,反正调试说是这里可以输入这么多就可以造成栈溢出了哈
【gdb之x命令】
可以使用examine命令(简写是x)来查看内存地址中的值。x命令的语法如下所示:
x/<n/f/u>
n、f、u是可选的参数。
n是一个正整数,表示需要显示的内存单元的个数,也就是说从当前地址向后显示几个内存单元的内容,一个内存单元的大小由后面的u定义。
f 表示显示的格式,参见下面。如果地址所指的是字符串,那么格式可以是s,如果地十是指令地址,那么格式可以是i。
u 表示从当前地址往后请求的字节数,如果不指定的话,GDB默认是4个bytes。u参数可以用下面的字符来代替,b表示单字节,h表示双字节,w表示四字 节,g表示八字节。当我们指定了字节长度后,GDB会从指内存定的内存地址开始,读写指定字节,并把其当作一个值取出来。
表示一个内存地址。
注意:严格区分n和u的关系,n表示单元个数,u表示每个单元的大小。
n/f/u三个参数可以一起使用。例如:
命令:x/3uh 0x54320 表示,从内存地址0x54320读取内容,h表示以双字节为一个单位,3表示输出三个单位,u表示按无符号十进制显示。
这里是copy的所以emem学习一下