5

私は、不十分な暗号化アルゴリズムで暗号化されたPDFを暗号化分析することになっている割り当てに取り組んでいます。

教授によって提供されたコードは、で暗号化されたファイルを作成しますfd=open(filename, O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR)

復号化を試みるコードで、そのファイルを。で開きますfd_in=open(file, O_RDONLY)

問題は、ファイルから読み込もうとすると、「不正なファイル記述子」エラーが発生することです。statを使用して、開かれたファイルについてファイル記述子が「考えた」ことに関する詳細情報を取得しようとしました。実際には数百KBの場合、ファイルの長さは0であることが示されています。

私が使用しているデバッグコードは次のとおりです。

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についていくつか質問がありました。暗号化/復号化プロセスには、読み取られた値のXORが含まれます。このため、バッファはとして宣言され、unsigned long longそれを読み込むために、アドレスを取得して(char *)にキャストします。この戦術は、暗号化されたファイルを作成するための教授のコードから直接出たものです。

ファイル記述子が有効になっていることを確認するために、printfでelseを追加しました。現時点では一貫しているようです3が、間違いなくそうではありません-1

4

3 に答える 3

2

open()との呼び出しの間にスタックが破損していないかどうかを確認してread()、ファイル記述子の値をfd_in変更することをお勧めします。

于 2012-10-29T14:16:01.627 に答える
0

申し訳ありませんが、これはコメントである必要があります。ここからコメントすることはできません。read_buffとは何ですか?なぜchar*にキャストするのですか?

char *read_buff;read_buffが次のように定義されている場合(fd, &read_buff, LEN);、バッファoveflowを実行して、自動変数を上書きする可能性があります。

于 2012-10-29T11:40:54.250 に答える
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;
}

この関数は、指定されたファイルを使用して、指定されたバイトまでminimummaximumバイトを読み取ります。成功した場合は0を返し、それ以外の場合はゼロ以外を返します。最小値を満たすのに十分なデータがない場合に返されます。bufferdescriptorerrnoENOENT

非ブロッキング記述子でビジーループを実行することにより、非ブロッキング記述子でも機能します(再試行して失敗するたびに現在のタイムスライスを生成するだけです)。つまり、非ブロッキング記述子で使用することはお勧めしませんが、何らかの奇妙な理由で使用する必要がある場合は、使用できます。する必要はありません。(実際、私は個人的にそのビットを削除します- EAGAIN/EWOULDBLOCKチェックしてsched_yield()-なので、記述子が非ブロッキングであるか、そうでなければならない場合は、適切なアプローチを使用するようにコードに気づき、修正します。)

于 2012-10-29T11:15:09.247 に答える