は、あなたがそれを行うことができます方法は次のとおりです。
// Compile with Borland's Turbo C++ 1.01
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <dos.h>
const char ScanToChar[] =
"??1234567890-=??"
"QWERTYUIOP[]??AS"
"DFGHJKL;\"`?\\ZXCV"
"BNM,./??? ";
void interrupt (*pOldInt9)(void);
void interrupt (*pOldInt1C)(void);
char far* pInDosFlag;
#define SCAN_BUF_SIZE 1024
volatile unsigned char ScanBuf[SCAN_BUF_SIZE];
volatile unsigned ScanReadIdx = 0;
volatile unsigned ScanWriteIdx = 0;
volatile unsigned LogFileHandle;
void DosWriteFile(unsigned handle, void* data, size_t size);
volatile unsigned InDos0cnt = 0;
void TryToSaveLog(void)
{
unsigned cnt;
if (*pInDosFlag)
return;
cnt = (ScanWriteIdx - ScanReadIdx) & (SCAN_BUF_SIZE - 1);
InDos0cnt++;
while (cnt--)
{
static const char hex[] = "ABCDEF";
char s[80] = "0xXX \"?\"\r\n";
unsigned char scanCode = ScanBuf[ScanReadIdx];
s[2] = hex[scanCode >> 4];
s[3] = hex[scanCode & 0xF];
if ((scanCode & 0x7F) < strlen(ScanToChar))
{
s[6] = ScanToChar[scanCode & 0x7F];
}
DosWriteFile(LogFileHandle, s, strlen(s));
ScanReadIdx++;
ScanReadIdx &= SCAN_BUF_SIZE - 1;
}
}
void interrupt NewInt9(void)
{
unsigned char scanCode = inp(0x60);
ScanBuf[ScanWriteIdx++] = scanCode;
ScanWriteIdx &= SCAN_BUF_SIZE - 1;
pOldInt9();
}
volatile unsigned int1Ccnt = 0;
void interrupt NewInt1C(void)
{
int1Ccnt++;
pOldInt1C();
TryToSaveLog();
}
unsigned DosCreateFile(const char* name)
{
union REGS regs;
struct SREGS sregs;
regs.h.ah = 0x3C;
regs.x.cx = 0;
sregs.ds = FP_SEG(name);
regs.x.dx = FP_OFF(name);
intdosx(®s, ®s, &sregs);
return regs.x.cflag ? 0 : regs.x.ax;
}
void DosWriteFile(unsigned handle, void* data, size_t size)
{
union REGS regs;
struct SREGS sregs;
if (!size) return;
regs.h.ah = 0x40;
regs.x.bx = handle;
regs.x.cx = size;
sregs.ds = FP_SEG(data);
regs.x.dx = FP_OFF(data);
intdosx(®s, ®s, &sregs);
}
void DosCloseFile(unsigned handle)
{
union REGS regs;
struct SREGS sregs;
regs.h.ah = 0x3E;
regs.x.bx = handle;
intdosx(®s, ®s, &sregs);
}
void StartLog(const char* FileName)
{
union REGS regs;
struct SREGS sregs;
LogFileHandle = DosCreateFile(FileName);
regs.h.ah = 0x34; // get InDos flag address
intdosx(®s, ®s, &sregs);
pInDosFlag = MK_FP(sregs.es, regs.x.bx);
pOldInt1C = getvect(0x1C);
setvect(0x1C, &NewInt1C);
pOldInt9 = getvect(9);
setvect(9, &NewInt9);
}
void EndLog(void)
{
setvect(9, pOldInt9);
while (ScanWriteIdx != ScanReadIdx);
setvect(0x1C, pOldInt1C);
DosCloseFile(LogFileHandle);
LogFileHandle = 0;
}
int main(void)
{
char str[256];
StartLog("keylog.txt");
printf("please enter some text:\n");
gets(str);
printf("you have entered \"%s\"\n", str);
EndLog();
printf("int 1Ch count: %u\n", int1Ccnt);
printf("InDos=0 count: %u\n", InDos0cnt);
return 0;
}
出力する(Windows XP上で実行):
please enter some text:
qweasdzxc123
you have entered "qweasdzxc123"
int 1Ch count: 175
InDos=0 count: 1
KEYLOG.TXT:
0x10 "Q"
0x90 "Q"
0x11 "W"
0x91 "W"
0x12 "E"
0x92 "E"
0x1E "A"
0x9E "A"
0x1F "S"
0x9F "S"
0x20 "D"
0xA0 "D"
0x2C "Z"
0xAC "Z"
0x2D "X"
0xAD "X"
0x2E "C"
0xAE "C"
0x02 "1"
0x82 "1"
0x03 "2"
0x83 "2"
0x04 "3"
0x84 "3"
0x1C "?"
いくつかの問題がありますここに。使用中のDOS機能は使用できません。これが私がInDos
フラグをチェックしている理由です。同時に、InDosは、キーボード入力などの簡単なことを待っているときでも、DOSがビジーであることを示すことができます(たとえば、gets()
)。
これは、プログラムがDOSファイルI/Oルーチンを安全に呼び出せない間に、それらを累積するスキャンコード用の循環バッファがあるためです。 EndLog()
はバッファがなくなるまで待ちます。早くも排水を強制する必要があるかもしれません。
また、int 1Chの代わりにint 28hをフックしようとしましたが、int 28hのISRが呼び出されることはありません。
バックグラウンドで起こって物事を知らないのですメインプログラムに干渉しないように私は、ログファイルのCのfopen()
とfwrite()
/fprintf()
の使用を避けています。同様の理由により、ISRで最も単純な標準C関数のみが使用されます。
'int 9'ハンドラから' int 21'を呼び出しましたが、それは爆発しませんでしたか? – ninjalj
あなたがそれらを正しく呼び出すと何も爆発しません。 – Bob