pwnable_tw_1(未完待续)

0x1

这题本来一点思路都没有,然后看到别人说的read_int可以是负数啊,这样就可以往任意地址写内容了~我们往GOT中写入我们的shellcode的地址,然后再去调用被覆盖的函数。

0x02

但是关键是shellcode的编写。输入会被一个叫is_printable()的函数过滤,函数原型如下。

1
2
3
4
5
6
7
8
9
10
11
int __cdecl is_printable(char *s)
{
size_t i; // [sp+Ch] [bp-Ch]@1
for ( i = 0; strlen(s) > i; ++i )
{
if ( s[i] <= 31 || s[i] == 127 )
return 0;
}
return 1;
}

这里虽然是s[i] <= 31 以及 s[i] == 0x7F 这两个条件会被过滤,但是在实际的shellcode调试中发现,s[i] <= 31 这个东西里面大有名堂,在汇编里面这个条件判别是这样的

1
2
.text:08048713 cmp al, 1Fh
.text:08048715 jle short loc_8048726

然后我就发现s[i] = 0x8f,0xf7等等都是无法满足这个条件的,然后去一查:这个cmp是有符号数的compare,所以al=(1XXXXXXX)b都是负数。。。那么自然是小于0x1F的,所以我们可以使用shellcode字符只有 0x20 < s[i] < 0x7E,另外就是这题限制了shellcode的长度。无奈汇编能力只能看看代码,而且接触机器码又是少之又少的,所以这个题目搁置了好久。跑去打pwnable.kr,然而今天kr访问不上去了~又拾起此题。

在网上找到这位仁兄的整理:pzhxbz的博客

首先整理一下在可打印范围内能用的汇编指令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
1.数据传送:
push/pop eax…
pusha/popa
2.算术运算:
inc/dec eax…
sub al, 立即数
sub byte ptr [eax… + 立即数], al dl…
sub byte ptr [eax… + 立即数], ah dh…
sub dword ptr [eax… + 立即数], esi edi
sub word ptr [eax… + 立即数], si di
sub al dl…, byte ptr [eax… + 立即数]
sub ah dh…, byte ptr [eax… + 立即数]
sub esi edi, dword ptr [eax… + 立即数]
sub si di, word ptr [eax… + 立即数]
3.逻辑运算:
and al, 立即数
and dword ptr [eax… + 立即数], esi edi
and word ptr [eax… + 立即数], si di
and ah dh…, byte ptr [ecx edx… + 立即数]
and esi edi, dword ptr [eax… + 立即数]
and si di, word ptr [eax… + 立即数]
xor al, 立即数
xor byte ptr [eax… + 立即数], al dl…
xor byte ptr [eax… + 立即数], ah dh…
xor dword ptr [eax… + 立即数], esi edi
xor word ptr [eax… + 立即数], si di
xor al dl…, byte ptr [eax… + 立即数]
xor ah dh…, byte ptr [eax… + 立即数]
xor esi edi, dword ptr [eax… + 立即数]
xor si di, word ptr [eax… + 立即数]
4.比较指令:
cmp al, 立即数
cmp byte ptr [eax… + 立即数], al dl…
cmp byte ptr [eax… + 立即数], ah dh…
cmp dword ptr [eax… + 立即数], esi edi
cmp word ptr [eax… + 立即数], si di
cmp al dl…, byte ptr [eax… + 立即数]
cmp ah dh…, byte ptr [eax… + 立即数]
cmp esi edi, dword ptr [eax… + 立即数]
cmp si di, word ptr [eax… + 立即数]
5.转移指令:
push 56h
pop eax
cmp al, 43h
jnz lable
<=> jmp lable
6.交换al, ah
push eax
xor ah, byte ptr [esp] // ah ^= al
xor byte ptr [esp], ah // al ^= ah
xor ah, byte ptr [esp] // ah ^= al
pop eax
7.清零:
push 44h
pop eax
sub al, 44h ; eax = 0
push esi
push esp
pop eax
xor [eax], esi ; esi = 0

我自己也找到了一份asm转machine-code 的资料
然而太多太杂,一时间看不完而且不好找。