我正在进行一项任务,我们应该对使用不良加密算法加密的PDF进行加密分析。
教程提供的代码使用fd=open(filename, O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR)
创建加密文件。
在我尝试解密的代码中,我使用fd_in=open(file, O_RDONLY)
打开该文件。
问题是,当我尝试从文件读入时,我收到“错误的文件描述符”错误。我使用stat来尝试获取有关文件描述符“关于”已打开文件的更多信息,并显示该文件的长度为0时实际为几百KB。
我正在使用的调试代码是:
if (0 > (len = read(fd_in, (char*)&read_buff, BITE))) { // BITE is defined as 8
printf("Error occured grabbing first bite of %s.\n", file);
printf("%s.\n", strerror(errno));
struct stat fileStat;
int stat = fstat(fd_in, &fileStat);
printf("fstat returned: %d.\n", stat); // Consistently printing 0
printf("Information for %s\n",file);
printf("---------------------------\n");
printf("File Size: \t\t%d bytes\n",fileStat.st_size);
printf("Number of Links: \t%d\n",fileStat.st_nlink);
printf("File inode: \t\t%d\n",fileStat.st_ino);
printf("File Permissions: \t");
printf( (S_ISDIR(fileStat.st_mode)) ? "d" : "-");
printf( (fileStat.st_mode & S_IRUSR) ? "r" : "-");
printf( (fileStat.st_mode & S_IWUSR) ? "w" : "-");
printf( (fileStat.st_mode & S_IXUSR) ? "x" : "-");
printf( (fileStat.st_mode & S_IRGRP) ? "r" : "-");
printf( (fileStat.st_mode & S_IWGRP) ? "w" : "-");
printf( (fileStat.st_mode & S_IXGRP) ? "x" : "-");
printf( (fileStat.st_mode & S_IROTH) ? "r" : "-");
printf( (fileStat.st_mode & S_IWOTH) ? "w" : "-");
printf( (fileStat.st_mode & S_IXOTH) ? "x" : "-");
printf("\n\n");
return 1;
}
我得到的结果是:
Error occured grabbing first bite of enc.pdf.
Bad file descriptor.
Information for enc.pdf
---------------------------
File Size: 0 bytes
Number of Links: 1
File inode: 16441996
File Permissions: -rw-------
ls将文件报告为
-rw------- 1 matt matt 157887 Oct 29 03:01 enc.pdf
与打开文件相关的代码:
int fd_in=open(file, O_RDONLY);
if(fd_in<0) {
printf("Failed to open the input file %s.\n", file);
return 1;
} else {
printf("File open, descriptor is: %d.\n", fd_in);
}
这一直在为字段描述符打印出值3。
有一些关于read_buff的问题。加密/解密过程涉及对读取的值进行异或。因此,缓冲区被声明为unsigned long long
,为了读入它,我获取地址并将其转换为(char *)。这种策略直接来自教授创建加密文件的代码。
我甚至添加了一个带有printf的else来验证文件描述符是否有效。目前它似乎是3
,但绝对不是-1
答案 0 :(得分:2)
您可能希望检查堆栈在open()
和read()
的调用之间是否已损坏,以便更改文件描述符fd_in
的值。
答案 1 :(得分:0)
您忽略了检查各种操作员的结果。在上面列出的代码中,我非常肯定fd_in == -1
。
要使用低级I / O打开数据文件,您需要执行以下操作:
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
...
int fd;
do {
fd = open(filename, O_RDONLY | O_NOCTTY);
} while (fd == -1 && errno == EINTR);
if (fd == -1) {
const char *const errmsg = strerror(errno);
fprintf(stderr, "%s: %s.\n", filename, errmsg);
exit(1);
}
这是因为open()
总是可以被打断。
read()
也可以被中断,但通常只返回一个简短的计数。
不,你不能只说“但它通常会读取我要求的所有内容,如果它发生,我会稍后解决”,因为它实际上取决于系统细节 - 特别是,文件碰巧驻留在哪个文件系统上。在不同的系统上运行会产生不同的结果 - 更不用说如果不是文件,它恰好是命名管道或字符设备。只有白痴才会认为read()
总会(甚至通常)读出你要求的所有内容。
强大的方法是使用辅助函数,或许类似于
#include <unistd.h>
#include <sys/types.h>
#include <sched.h>
#include <errno.h>
/* Read between minimum and maximum bytes (inclusive)
* from descriptor to buffer. Save the number of bytes
* read into *bytes if bytes is not NULL.
* The function returns 0 if successful, errno error otherwise.
* If there is less input than minimum bytes, the function
* will return ENOENT.
*/
static inline int readfd(const int descriptor,
void *const buffer,
const size_t minimum,
const size_t maximum,
size_t *const bytes)
{
size_t have = 0;
ssize_t n;
while (have < minimum) {
n = read(descriptor, (char *)buffer + have, maximum - have);
if (n > (ssize_t)0) {
have += n;
if (bytes)
*bytes = have;
} else
if (n == (ssize_t)0) {
/* EOF, and have < minimum. */
return errno = ENOENT;
} else
if (n != (ssize_t)-1) {
/* A rare I/O error (Linux kernel bug). */
return errno = EIO;
} else
if (errno == EWOULDBLOCK || errno == EAGAIN) {
/* Nonblocking descriptor; ouch. Busy-loop. */
sched_yield();
} else
if (errno != EINTR)
return errno;
}
return 0;
}
该函数将使用指定的文件minimum
在maximum
和buffer
字节之间读取指定的descriptor
。如果成功,它将返回0,否则返回非零errno
。如果没有足够的数据来满足最小值,它将返回ENOENT
。
它甚至可以在非阻塞描述符上工作,通过对非阻塞描述符进行忙循环(每次重试和失败时只产生当前时间片)。这意味着不建议将其与非阻塞描述符一起使用,但如果由于某些奇怪的原因需要,则可以。你应该不需要。 (事实上,我个人放弃了这一点 - EAGAIN
/ EWOULDBLOCK
检查和sched_yield()
- 所以我会注意到并修复我的代码以使用正确的方法,如果描述符是或必须是非阻塞的。)
答案 2 :(得分:0)
对不起,这应该是评论。不能在这里发表评论。 什么是read_buff?你为什么要施展为char *?
如果 read_buff定义为char *read_buff;
,则(fd, &read_buff, LEN);
可以执行缓冲区溢出,覆盖自动变量。