📄 dirsh.c
字号:
/* dirsh version 1.1
* author 谈子龙
* last modified date: April 25th, 2009
*/
#include "dirsh.h"
#include "rc4.h"
#include "md5.h"
#include "map.h"
char *Usage =
"directory shield 1.1, by Enigma, c32asm@gmail.com\n"\
"usage: dirsh [options] dir\n"\
"options:\n"\
" -e encryption mode\n"\
" -d decryption mode\n"\
" -k<key> specify encryption/decryption key\n"\
" -b<size> encrypt/decrypt block size in byte\n"\
" -r<len> generate random name for file\n"\
" -c<cmd> execute one command for each file\n"\
" -i<str> replace str in cmd with the full file name, used with -c\n"\
" -p<pattern> matching file names in dir with the given pattern\n"\
" -l<file> generate a md5 index for each file content\n"\
" -s recover file names from md5 index after decryption\n"\
" -v verbose output\n";
void clearList(List ls)
{
List next;
while(ls){
next = ls->next;
free(ls);
ls = next;
}
}
void printList(List ls)
{
List pnode = ls;
while(pnode){
printf("%s\\%s\n", pnode->dir, pnode->ffd.cFileName);
pnode = pnode->next;
}
}
static List getLastNode(List begin)
{
List end = begin;
if(end == NULL)
return NULL;
while(end->next)
end = end->next;
return end;
}
static BOOL deleteNode(List *pls, List pnode)
{
if(pls == NULL || pnode == NULL)
return FALSE;
if(*pls == pnode){
*pls = pnode->next;
free(pnode);
return TRUE;
}
while(*pls && (*pls)->next != pnode)
*pls = (*pls)->next;
if(*pls){
(*pls)->next = pnode->next;
free(pnode);
return TRUE;
}
return FALSE;
}
// generate a list of file under root
static List listFile(char *root, char *pattern)
{
HANDLE hFind;
List ls = NULL, lastnode;
WIN32_FIND_DATA ffd;
char currentdir[MAX_PATH];
if(!SetCurrentDirectory(root))
return NULL;
GetCurrentDirectory(MAX_PATH, currentdir);
if((hFind = FindFirstFile(pattern, &ffd)) == INVALID_HANDLE_VALUE){
SetCurrentDirectory("..");
return NULL;
}
do{
if(*ffd.cFileName != '.'){
if(ls == NULL){
if((ls = (List)malloc(sizeof(Node))) == NULL){
fprintf(stderr, "Failed to allocate memory for node.\n");
break;
}
strncpy(ls->dir, currentdir, MAX_PATH);
ls->ffd = ffd;
if(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){
ls->next = listFile(ffd.cFileName, pattern);
lastnode = getLastNode(ls);
}else{
ls->next = NULL;
lastnode = ls;
}
}else{
if((lastnode->next = (List)malloc(sizeof(Node))) == NULL){
fprintf(stderr, "Failed to allocate memory for node.\n");
break;
}
lastnode = lastnode->next;
strncpy(lastnode->dir, currentdir, MAX_PATH);
lastnode->ffd = ffd;
if(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){
lastnode->next = listFile(ffd.cFileName, pattern);
lastnode = getLastNode(lastnode);
}else
lastnode->next = NULL;
}
}
}while(FindNextFile(hFind, &ffd));
SetCurrentDirectory("..");
FindClose(hFind);
return ls;
}
// return the hex string of a sequence of random bytes
// len is the size of random bytes
char* getRandString(char *buf, int buf_len, int len)
{
int i;
if(buf == NULL || len == 0 || len >= buf_len){
fprintf(stderr, "In getRandString: required length: %d, buffer size: %d.\n", len, buf_len);
return NULL;
}
len = len/ 2;
for(i = 0; i < len; i++)
sprintf(&buf[i * 2], "%02X", (unsigned char)rand() & 0xFF);
return buf;
}
// returns FALSE if NO, otherwise TRUE is returned
BOOL getYesNo(char *msg)
{
char c;
printf("%s", msg);
if((c = getchar()) != 'N' && c != 'n')
return TRUE;
return FALSE;
}
// replace file names with specified length random digits
void randFile(List ls, DWORD rnd_len)
{
List pnode = ls;
char buf[RND_NAME_MAXLEN + 1];
srand(time(NULL));
while(pnode){
if((pnode->ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0){
if(!SetCurrentDirectory(pnode->dir) ||
rename(pnode->ffd.cFileName, getRandString(buf, sizeof(buf), rnd_len))){
fprintf(stderr, "Failed to randomize %s\\%s\n",
pnode->dir,
pnode->ffd.cFileName);
if(getYesNo("Exclude it from list?(Y/N): "))
deleteNode(&ls, pnode);
}else
strncpy(pnode->ffd.cFileName, buf, MAX_PATH); // update list with new file name
}
pnode = pnode->next;
}
}
char *getPW(char *pw_buf)
{
int i, j;
int ch;
char two_pw[PASSWORD_MAXLEN * 2 + 2]; // store first and retyped password strings
if(pw_buf == NULL)
return NULL;
do{
for(i = 0; i < 2; i++){
if(!i)
printf("Enter password : ");
else
printf("Verify password: ");
for(j = 0; j < PASSWORD_MAXLEN;){
ch = getch();
if(ch == '\b'){
if(j){
j--;
printf("\b \b");
}
}else if(ch == 0x0D)
break;
else{
two_pw[i * (PASSWORD_MAXLEN + 1) + j++] = ch;
putchar('*');
}
}
printf("\n");
two_pw[i * (PASSWORD_MAXLEN + 1) + j] = '\0';
}
}while(strcmp(two_pw, two_pw + PASSWORD_MAXLEN + 1));
strncpy(pw_buf, two_pw, PASSWORD_MAXLEN + 1);
return pw_buf;
}
// encrypt file using RC4
static BOOL encodeFile(char *dir, char *file, char *key, DWORD blk_size)
{
HANDLE hFile;
HANDLE hTemp;
DWORD nRead;
char *temp;
char buf[FILE_BUFFER_LEN];
rc4_key rc4key;
SetCurrentDirectory(dir);
if((hFile = CreateFile(file, GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE){
fprintf(stderr, "Failed to open file %s\n", file);
return FALSE;
}
prepare_key(key, strlen(key), &rc4key);
if(!blk_size){
temp = tmpnam(NULL);
if((hTemp = CreateFile(temp, GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL)) == INVALID_HANDLE_VALUE){
fprintf(stderr, "Failed to open temp file %s\n", temp);
CloseHandle(hFile);
return FALSE;
}
while(ReadFile(hFile, buf, sizeof(buf), &nRead, NULL) && nRead){
rc4((unsigned char*)buf, nRead, &rc4key);
WriteFile(hTemp, buf, nRead, &nRead, NULL);
}
CloseHandle(hFile);
CloseHandle(hTemp);
DeleteFile(file);
if(rename(temp, file)){
fprintf(stderr, "Failed to update file %s with new file %s\n", file, temp);
return FALSE;
}
}else{
while(blk_size && ReadFile(hFile,
buf, blk_size > sizeof(buf)? sizeof(buf): blk_size, &nRead, NULL) && nRead){
blk_size -= nRead;
rc4((unsigned char*)buf, nRead, &rc4key);
SetFilePointer(hFile, -(int)nRead, 0, FILE_CURRENT);
WriteFile(hFile, buf, nRead, &nRead, NULL);
}
CloseHandle(hFile);
}
return TRUE;
}
char *getNewName(char *old_buf, char *new_buf, char *key)
{
rc4_key rc4key;
int len = strlen(old_buf);
int i;
char byte_str[] = {0, 0, 0};
unsigned char bytes[(RND_NAME_MAXLEN + 1) / 2];
if(len & 1 || len > RND_NAME_MAXLEN)
return NULL;
for(i = 0; i < len; i += 2){
byte_str[0] = old_buf[i];
byte_str[1] = old_buf[i + 1];
bytes[i >> 1] = (unsigned char)strtoul(byte_str, 0, 16);
}
prepare_key(key, strlen(key), &rc4key);
rc4(bytes, len >> 1, &rc4key);
for(i = 0; i < len; i += 2)
sprintf(&new_buf[i], "%02X", bytes[i >> 1]);
return new_buf;
}
/*
if rnd_mode is TRUE, the key used to encrypt/decrypt file is the old name
of the file, after that, we use the entered key to encrypt old file name
to produce the new name of file. Otherwise, we encrypt/decrypt file using
the entered key directly.
*/
// enc_mode:
// TRUE: Encryption
// FALSE: Decryption
void encodeList(List ls, char *key, DWORD blk_size, BOOL rnd_mode, BOOL enc_mode)
{
char pw_buf[PASSWORD_MAXLEN + 1];
char newName[RND_NAME_MAXLEN + 1];
char bar[] = "[ ]";
List pnode = ls;
int nNode = 0;
int iNode = 0;
int iBar = 1;
int iBarNext;
float percent;
// calculates the number of node
while(ls){
if((ls->ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
nNode++;
ls = ls->next;
}
while(!key || !*key)
key = getPW(pw_buf);
while(pnode){
if((pnode->ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0){
if(!rnd_mode)
encodeFile(pnode->dir, pnode->ffd.cFileName, key, blk_size);
else if(enc_mode){
encodeFile(pnode->dir, pnode->ffd.cFileName, pnode->ffd.cFileName, blk_size);
if(!SetCurrentDirectory(pnode->dir) ||
rename(pnode->ffd.cFileName,
getNewName(pnode->ffd.cFileName, newName, key)))
fprintf(stderr, "SECURITY ALERT: Cannot update file name %s with %s\n",
pnode->ffd.cFileName, newName);
else
strncpy(pnode->ffd.cFileName, newName, MAX_PATH);
}else{
if(!SetCurrentDirectory(pnode->dir) ||
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -