CreateMutex
까보면 다나와~
유용한 지식 자료들 (89)

windows-anti-debug-reference


http://www.symantec.com/connect/articles/windows-anti-debug-reference


by Nicolas Falliere

This paper classifies and presents several anti-debugging techniques used on Windows NT-based operating systems. Anti-debugging techniques are ways for a program to detect if it runs under control of a debugger. They are used by commercial executable protectors, packers and malicious software, to prevent or slow-down the process of reverse-engineering. We'll suppose the program is analyzed under a ring3 debugger, such as OllyDbg on Windows platforms. The paper is aimed towards reverse-engineers and malware analysts. Note that we will talk purely about generic anti-debugging and anti-tracing techniques. Specific debugger detection, such as window or processes enumeration, registry scanning, etc. will not be addressed here.

[1] Intro

This paper classifies and presents several anti-debugging techniques used on Windows NT-based operating systems.
Anti-debugging techniques are ways for a program to detect if it runs under control of a debugger. They are used by commercial executable protectors, packers and malicious software, to prevent or slow-down the process of reverse-engineering.

We'll suppose the program is analyzed under a ring3 debugger, such as OllyDbg on Windows platforms. The paper is aimed towards reverse-engineers and malware analysts.
Note that we will talk purely about generic anti-debugging and anti-tracing techniques. Specific debugger detection, such as window or processes enumeration, registry scanning, etc. will not be addressed here.

[2] Anti-debugging and anti-tracing techniques

- Exploiting memory discrepancies

(1) kernel32!IsDebuggerPresent
IsDebuggerPresent returns 1 if the process is being debugged, 0 otherwise. This API simply reads the PEB!BeingDebugged byte-flag (located at offset 2 in the PEB structure).
Circumventing it is as easy as setting PEB!BeingDebugged to 0.
Example:
call IsDebuggerPresent
test eax, eax
jne @DebuggerDetected
...

(2) PEB!IsDebugged
This field refers to the second byte in the Process Environment Block of the process. It is set by the system when the process is debugged.
This byte can be reset to 0 without consequences for the course of execution of the program (it is an informative flag).

Example:
mov eax, fs:[30h]
mov eax, byte [eax+2]
test eax, eax
jne @DebuggerDetected
...

(3) PEB!NtGlobalFlags
When a process is created, the system sets some flags that will define how various APIs will behave for this program. Those flags can be read in the PEB, in the DWORD located at offset 0x68 (see the reference).
By default, different flags are set depending if the process is created under a debugger or not. If the process is debugged, some flags controlling the heap manipulation routines in ntdll will be set: FLG_HEAP_ENABLE_TAIL_CHECK, FLG_HEAP_ENABLE_FREE_CHECK and FLG_HEAP_VALIDATE_PARAMETERS.
This anti-debug can be bypassed by resetting the NtGlobalFlags field.

Example:
mov eax, fs:[30h]
mov eax, [eax+68h]
and eax, 0x70
test eax, eax
jne @DebuggerDetected
...

(4) Heap flags
As explained previously, NtGlobalFlags informs how the heap routines will behave (among other things). Though it is easy to modify the PEB field, if the heap does not behave the same way as it should when the process is not debugged, this could be problematic. It is a powerful anti-debug, as process heaps are numerous, and their chunks can be individually affected by the FLG_HEAP_* flags (such as chunk tails). Heap headers would be affected as well. For instance, checking the field ForceFlags in a heap header (offset 0x10) can be used to detect the presence of a debugger.

There are two easy ways to circumvent it:

- Create a non-debugged process, and attach the debugger once the process has been created (an easy solution is to create the process suspended, run until the entry-point is reached, patch it to an infinite loop, resume the process, attach the debugger, and restore the original entry-point).

- Force the NtGlobalFlags for the process that we want to debug, via the registry key "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options": Create a subkey (not value) named as your process name, and under this subkey, a String value "GlobalFlags" set to nothing.

Example:
mov eax, fs:[30h]
mov eax, [eax+18h] ;process heap
mov eax, [eax+10h] ;heap flags
test eax, eax
jne @DebuggerDetected
...

(5) Vista anti-debug (no name)
Here's an anti-debug specific to Windows Vista that I found by comparing memory dumps of a program running with and without control of a debugger. I'm not sure of its realiability, but it's worth mentionning (tested on Windows Vista 32 bits, SP0, English version).

When a process is debugged, its main thread TEB, at offset 0xBFC, contains a pointer to a unicode string referencing a system dll. Moreover, the string follows this pointer (therefore, located at offset 0xC00 in the TEB). If the process is not debugged, the pointer is set to NULL and the string is not present.

Example:
call GetVersion
cmp al, 6
jne @NotVista
push offset _seh
push dword fs:[0]
mov fs:[0], esp
mov eax, fs:[18h] ; teb
add eax, 0BFCh
mov ebx, [eax] ; pointer to a unicode string
test ebx, ebx ; (ntdll.dll, gdi32.dll,...)
je @DebuggerNotFound
sub ebx, eax ; the unicode string follows the
sub ebx, 4 ; pointer
jne @DebuggerNotFound
;debugger detected if it reaches this point
;...

- Exploiting system discrepancies

(1) NtQueryInformationProcess
ntdll!NtQueryInformationProcess is a wrapper around the ZwQueryInformationProcess syscall. Its prototype is the following:

NTSYSAPI NTSTATUS NTAPI NtQueryInformationProcess(
IN HANDLE ProcessHandle,
IN PROCESS_INFORMATION_CLASS ProcessInformationClass,
OUT PVOID ProcessInformation,
IN ULONG ProcessInformationLength,
OUT PULONG ReturnLength
);

When called with ProcessInformationClass set to 7 (ProcessDebugPort constant), the system will set ProcessInformation to -1 if the process is debugged.
It is a powerful anti-debug, and there is no easy way to circumvent it. However, if the program is traced, ProcessInformation can be modified when the syscall returns.

Another solution is to use a system driver that would hook the ZwNtQueryInformationProcess syscall.
Circumventing NtQueryInformationProcess will bypass many anti-debug techniques (such as CheckRemoteDebuggerPresent or UnhandledExceptionFilter).

Example:
push 0
push 4
push offset isdebugged
push 7 ;ProcessDebugPort
push -1
call NtQueryInformationProcess
test eax, eax
jne @ExitError
cmp isdebugged, 0
jne @DebuggerDetected
...

(2) kernel32!CheckRemoteDebuggerPresent
This API takes two parameters: a process handle, and a pointer to a DWORD. If the call is successful, the DWORD value will be set to 1 if the process is being debugged.
Internally, this API calls ntdll!NtQueryInformationProcess with ProcessInformationClass set to ProcessDebugPort (7).

Example:
push offset isdebugged
push -1
call CheckRemoteDebuggerPresent
test eax, eax
jne @DebuggerDetected
...

(3) UnhandledExceptionFilter
When an exception occurs, with Windows XP SP>=2, Windows 2003, and Windows Vista, the usual way the OS processes the exception is:

- If any, pass control to the per-process Vectored Exception Handlers.
- If the exception is not processed, pass the control to the per-thread top SEH handler, pointed by FS:[0] in the thread that generated the exception. SEH are chained and called in turn if the exception is not processed by the previous in the chain.
- If the exception has not been processed by any of the previous handlers, the final SEH handler (set by the system), will call kernel32!UnhandledExceptionFilter. This function will decide what it should do depending if the process is debugged or not.
- If it is not debugged, it will call the user-defined filter function (set via kernel32!SetUnhandledExceptionFilter).
- If it debugged, the program will be terminated.

The debugger detection in UnhandledExceptionFilter is made with ntdll!NtQueryInformationProcess.

Example:
push @not_debugged
call SetUnhandledExceptionFilter
xor eax, eax
mov eax, dword [eax] ; trigger exception
;program terminated if debugged
;...
@not_debugged:
;process the exception
;continue the execution
;...

(4) NtSetInformationThread
ntdll!NtSetInformationThread is a wrapper around the ZwSetInformationThread syscall. Its prototype is the following:
NTSYSAPI NTSTATUS NTAPI NtSetInformationThread(
IN HANDLE ThreadHandle,
IN THREAD_INFORMATION_CLASS ThreadInformationClass,
IN PVOID ThreadInformation,
IN ULONG ThreadInformationLength
);

When called with ThreadInformationClass set to 0x11 (ThreadHideFromDebugger constant), the thread will be detached from the debugger.

Similarly to ZwQueryInformationProcess, circumventing this anti-debug requires either modifying ZwSetInformationThread parameters before it's called, or hooking the syscall directly with the use of a kernel driver.

Example:
push 0
push 0
push 11h ;ThreadHideFromDebugger
push -2
call NtSetInformationThread
;thread detached if debugged
;...

(5) kernel32!CloseHandle and NtClose
APIs making user of the ZwClose syscall (such as CloseHandle, indirectly) can be used to detect a debugger. When a process is debugged, calling ZwClose with an invalid handle will generate a STATUS_INVALID_HANDLE (0xC0000008) exception.

As with all anti-debugs that rely on information made directly available from the kernel (therefore involving a syscall), the only proper way to bypass the "CloseHandle" anti-debug is to either modify the syscall data from ring3, before it is called, or set up a kernel hook.

This anti-debug, though extremely powerful, does not seem to be widely used by malicious programs.

Example:
push offset @not_debugged
push dword fs:[0]
mov fs:[0], esp
push 1234h ;invalid handle
call CloseHandle
; if fall here, process is debugged
;...
@not_debugged:
;...

(6) Self-debugging
A process can detect it is being debugged by trying to debug itself, for instance by creating a new process, and calling kernel32!DebugActiveProcess(pid) on the parent process.

In turn, this API calls ntdll!DbgUiDebugActiveProcess which will call the syscall ZwDebugActiveProcess. If the process is already debugged, the syscall fails. Note that retrieving the parent process PID can be done with the toolhelp32 APIs (field th32ParentProcessID in the PROCESSENTRY32 structure.

(7) Kernel-mode timers
kernel32!QueryPerformanceCounter is an efficent anti-debug. This API calls ntdll!NtQueryPerformanceCounter which wraps the ZwQueryPerformanceCounter syscall.

Again, there is no easy way to circumvent this anti-tracing trick.

(8) User-mode timers
An API such as kernel32!GetTickCount returns the number of milliseconds ellapsed since the system started. The interesting thing is that it does not make use of kernel-related service to perform its duties. A user-mode process has this counter mapped in its address space. For 8Gb user-mode spaces, the value returned would be:

d[0x7FFE0000] * d[0x7FFE0004] / (2^24)

(9) kernel32!OutputDebugStringA
This anti-debug is quite original, I have encountered it only once, in files packed with ReCrypt v0.80. The trick consists of calling OutputDebugStringA, with a valid ASCII string. If the program is run under control of a debugger, the return value will be the address of the string passed as a parameter. In normal conditions, the return value should be 1.

Example:
xor eax, eax
push offset szHello
call OutputDebugStringA
cmp eax, 1
jne @DebuggerDetected
...

(10) Ctrl-C
When a console program is debugged, a Ctrl-C signal will throw a EXCEPTION_CTL_C exception, whereas the signal handler would be called directly is the program is not debugged.

Example:
push offset exhandler
push 1
call RtlAddVectoredExceptionHandler
push 1
push sighandler
call SetConsoleCtrlHandler
push 0
push CTRL_C_EVENT
call GenerateConsoleCtrlEvent
push 10000
call Sleep
push 0
call ExitProcess
exhandler:
;check if EXCEPTION_CTL_C, if it is,
;debugger detected, should exit process
;...
sighandler:
;continue
;...

- CPU anti-debug

(1) Rogue Int3
This is a classic anti-debug to fool weak debuggers. It consists of inserting an INT3 opcode in the middle of a valid sequence of instructions. When the INT3 is executed, if the program is not debugged, control will be given to the exception handler of the protection and execution will continue.

As INT3 instructions are used by debuggers to set software breakpoints, inserting INT3 opcodes can be used to trick the debugger into believing that it is one his breakpoints. Therefore, the control would not be given to the exception handler, and the course of the program would be modified. Debuggers should track where they set software breakpoints to avoid falling for this one.

Similarly, note that INT3 may be encoded as 0xCD, 0x03.

Example:
push offset @handler
push dword fs:[0]
mov fs:[0], esp
;...
db 0CCh
;if fall here, debugged
;...
@handler:
;continue execution
;...

(2) "Ice" Breakpoint
The so-called "Ice breakpoint" is one of Intel's undocumented instruction, opcode 0xF1. It is used to detect tracing programs.

Executing this instruction will generate a SINGLE_STEP exception. Therefore, if the program is already traced, the debugger will think it is the normal exception generated by executing the instruction with the SingleStep bit set in the Flags registers. The associated exception handler won't be executed, and execution will not continue as expected.
Bypassing this trick is easy: one can run over the instruction, instead and single-stepping on it. The exception will be generated, but since the program is not traced, the debugger should understand that it has to pass control to the exception handler.

Example:
push offset @handler
push dword fs:[0]
mov fs:[0], esp
;...
db 0F1h
;if fall here, traced
;...
@handler:
;continue execution
;...

(3) Interrupt 2Dh
Executing this interrupt if the program is not debugged will raise a breakpoint exception. If the program is debugged, and the instruction is not executed with the trace flag, no exception will be generated, and execution will carry on normally. If the program is debugged and the instruction traced, the following byte will be skipped, and execution will continue. Therefore, using INT 2Dh can be used as a powerful anti-debug and anti-tracer mechanism.
Example:
push offset @handler
push dword fs:[0]
mov fs:[0], esp
;...
db 02Dh
mov eax, 1 ;anti-tracing
;...
@handler:
;continue execution
;...

(4) Timestamp counters
High precision counters, storing the current number of CPU cycles executed since the machine started, can be queried with the RDTSC instruction. Classic anti-debugs consist of measuring time deltas at key points in the program, usually around exception handlers. If the delta is too large, that would mean the program runs under control of a debugger (processing the exception in the debugger, and giving control back to the debuggee is a lengthy task).

Example:
push offset handler
push dword ptr fs:[0]
mov fs:[0],esp
rdtsc
push eax
xor eax, eax
div eax ;trigger exception
rdtsc
sub eax, [esp] ;ticks delta
add esp, 4
pop fs:[0]
add esp, 4
cmp eax, 10000h ;threshold
jb @not_debugged
@debugged:
...
@not_debugged:
...
handler:
mov ecx, [esp+0Ch]
add dword ptr [ecx+0B8h], 2 ;skip div
xor eax, eax
ret

(5) Popf and the trap flag
The trap flag, located in the Flags register, controls the tracing of a program. If this flag is set, executing an instruction will also raise a SINGLE_STEP exception. The trap flag can be manipulated in order to thwart tracers. For instance, this sequence of instructions will set the trap flag:

pushf
mov dword [esp], 0x100
popf

If the program is being traced, this will have no real effect on the flags register, and the debugger will process the exception, believing it comes from regular tracing. The exception handler won't be executed. Circumventing this anti-tracer trick simply require to run over the pushf instruction.

(6) Stack Segment register
Here's a very original anti-tracer. I encountered it in a packer called MarCrypt. I believe it is not widely known, not to mention, used.
It consists of tracing over this sequence of instructions:

push ss
pop ss
pushf
nop

When tracing over pop ss, the next instruction will be executed but the debugger will not break on it, therefore stopping on the following instruction (NOP in this case).
Marcrypt uses this anti-debug the following way:

push ss
; junk
pop ss
pushf
; junk
pop eax
and eax, 0x100
or eax, eax
jnz @debugged
; carry on normal execution

The trick here is that, if the debugger is tracing over that sequence of instructions, popf will be excuted implicitly, and the debugger will not be able to unset the trapflag in the pushed value on the stack. The protection checks for the trap flag and terminates the program if it's found.
One simple way to circumvent this anti-tracing is to breakpoint on popf and run the program (to avoid using the TF flag).

(7) Debug registers manipulation
Debug registers (DR0 through DR7) are used to set hardware breakpoints. A protection can manipulate them to either detect that hardware breakpoints have been set (and therefore, that it is being debugged), reset them or set them to particular values used to perform code checks later. A packer such as tElock makes use of the debug registers to prevent reverse-engineers from using them.
From a user-mode perspective, debug registers cannot be set using the privileged 'mov drx, ...' instruction. Other ways exist:

- An exception can be generated, the thread context modified (it contains the CPU registers at the time the exception was thrown), and then resumed to normal execution with the new context.

- The other way is to use the NtGetContextThread and NtSetContextThread syscalls (available in kernel32 with GetThreadContext and SetThreadContext).

Most protectors use the first, "unofficial" way.

Example:
push offset handler
push dword ptr fs:[0]
mov fs:[0],esp
xor eax, eax
div eax ;generate exception
pop fs:[0]
add esp, 4
;continue execution
;...
handler:
mov ecx, [esp+0Ch] ;skip div
add dword ptr [ecx+0B8h], 2 ;skip div
mov dword ptr [ecx+04h], 0 ;clean dr0
mov dword ptr [ecx+08h], 0 ;clean dr1
mov dword ptr [ecx+0Ch], 0 ;clean dr2
mov dword ptr [ecx+10h], 0 ;clean dr3
mov dword ptr [ecx+14h], 0 ;clean dr6
mov dword ptr [ecx+18h], 0 ;clean dr7
xor eax, eax
ret

(8) Context modification
As with debug registers manipulation, the context can also be used to modify in an unconventionnal way the execution stream of a program. Debuggers can get easily confused!
Note that another syscall, NtContinue, can be used to load a new context in the current thread (for instance, this syscall is used by the exception handler manager).

- Uncategorized anti-debug

(1) TLS-callback
This anti-debug was not so well-known a few years ago. It consists to instruct the PE loader that the first entry point of the program is referenced in a Thread Local Storage entry (10th directory entry number in the PE optional header). By doing so, the program entry-point won't be executed first. The TLS entry can then perform anti-debug checks in a stealthy way.
Note that in practice, this technique is not widely used.
Though older debuggers (including OllyDbg) are not TLS-aware, counter-measures are quite easy to take, by the means of plugins of custom patcher tools.

(2) CC scanning
A common protection feature used by packers is the CC-scanning loop, aimed at detecting software breakpoints set by a debugger. If you want to avoid that kind of troubles, you may want to use either hardware breakpoints or a custom type of software breakpoint. CLI (0xFA) is a good candidate to replace the classic INT3 opcode. This instruction does have the requirements for the job: it raises a privileged instruction exception if executed by a ring3 program, and occupies only 1 byte of space.

(3) EntryPoint RVA set to 0
Some packed files have their entry point RVA set to 0, which means they will start executing 'MZ...' which corresponds to 'dec ebx / pop edx ...'.

This is not an anti-debug trick in itself, but can be annoying if you want to break on the entry-point by using a software breakpoint.

If you create a suspended process, then set an INT3 at RVA 0, you will erase part of the magic MZ value ('M'). The magic was checked when the process was created, but it will get checked again by ntdll when the process is resumed (in the hope of reaching the entry-point). In that case, an INVALID_IMAGE_FORMAT exception will be raised.

If you create your own tracing or debugging tool, you will want to use hardware breakpoint to avoid this problem.

[3] Conclusion

Knowing anti-debugging and anti-tracing techniques (un)commonly used by malware or protectors is useful knowledge for a reverse-engineer. A program will always have ways to find it is run in a debugger - the same applies for virtual or emulated environments, but since ring3 debuggers are some of the most common analysis tools used, knowing common tricks, and how to bypass them, will always prove useful.



[4] Links

MSDN
Portable Executable Tutorial, Matt Pietrek
Syscall Reference, The Metasploit Project
Undocumented Functions for MS Windows NT/2K
Intel Manuals
- Common exception codes - Microsoft Windows SDK, ntdll.h
- Status codes list (including common exception codes) - Microsoft Windows DDK, ntstatus.h
- Context Structures documentation - Microsoft Windows SDK, ntdll.h

....

  Comments,     Trackbacks

Malware online databases and analysis sites
  Comments,     Trackbacks

안티안티모니터링을 위한 API

FindWindowA
GetForegroundWindow
GetWindowTextA
CreateFileA

안티안티모니터링을 위한 API

BreakPoint

'유용한 지식 자료들 > Anti Reversing 기법' 카테고리의 다른 글

CMPXCHG8B and LOCK  (0) 2011.11.29
Red Pill  (1) 2011.11.29
OpenRCE Anti Reverse Engineering Techniques Database  (0) 2011.11.29
windows-anti-debug-reference  (0) 2011.11.29
Anti Debug 몇 가지 입니다.  (0) 2010.05.12
  Comments,     Trackbacks

Ubuntu 10.04 LTS, PXE + Truman 설치

기초 지식,
# Ubuntu 10.04 LTS는 NTFS를 마운트 하기 위한 별도의 패키지가 필요하지 않다.
# Ubuntu 10.04 LTS의 PXE 셋팅을 위해서는 DHCP server(dhcp3-server), TFTP server(xinetd + tftpd-hpa)가 셋팅되어야 한다.
# xinetd와 inetd는 같이 설치될 수 없다. inetd는 openbsd-inetd가 있다.(Truman은 xinetd가 필요)
# 만약 VMware 내에서 Network 구성을 하고자 하면 같은 NIC을 가지고 하면 된다.

1. apt-get -y install dhcp3-server apache2 xinetd tftpd-hpa
::PXE 구성을 위해

2. apt-get -y install tcpdump ngrep wireshark
::Truman 설치를 위해

3. 그외 각종 설정...차후 보강
  Comments,     Trackbacks

Volume, Cluster, Block, Page, Sector

정리가 안돼서 일단 적어본다.

Volume - 디스크에서 하나의 논리적인 파티션.
Cluster - Sector들의 모음, Windows에서 사용하는 모든 파일 시스템은 파일을 저장하기 위해 할당할 수 있는 가장 작은 디스크 공간을 나타내는 클러스터 크기를 기반으로 하드디스크를 구성
FAT 시스템에서는 512 바이트 단위로 맞춰져있음.

Cluster의 경우 512 byte ~ 4 kbyte단위로 각각 나뉘는데
512byte는 1 Cluster가 1 Sector, 4 kbyte는 1 Cluster가 8 Sector이다.
클러스터 크기 최대 NTFS 볼륨 크기(바이트 RAW)
512 2,199,023,255,552(2TB)
1024 4,398,046,511,104(4TB)
2048 8,796,093,022,208(8TB)
4096 17,592,186,044,416(17TB)

볼륨 크기 NTFS 클러스터 크기
7MB - 512MB 512바이트
513MB - 1,024MB 1KB
1,025MB - 2GB 2KB
2GB - 2TB 4KB

따라서 클러스터는 파일 저장에 필요한 최소한의 단위이고, Sector는 클러스터 크기를 지정하는 기준이 되는 것으로 512바이트를 보통 사용한다.

하지만 새로운 하드디스크의 경우 4096 byte를 한 Sector로 사용한다.(-_-).



Block - 이것은 NTFS에서 사용하는 클러스터와 같은 것임
Page - 물리디스크를 논리적으로 분리할때 필요한 단위....(-_-), 4096 byte가 1 page라고.. 알고있음.


총 정리하면...확실하지 않지만,,
Volume은 파티션이고, Cluster는 sector(512)들의 묶음이자 데이터 블록으로도 불린다. 보통 Cluster는 4096 kib(8 sector) 크기이며, Logical Block Address(LBA)는 하드시스크 전체에서 본 Sector의 주소라고 보면 될 것 같다.

http://www.ntfs.com/hard-disk-basics.htm
여기에 더 잘 나와있음.

almost always 512 bytes in size because 512
if the file size is 800 bytes, two 512 k sectors are allocated for the file.
Cluster size can be changed to optimize file storage.


따라서 클러스터의 크기는 가변적이고 섹터의 크기는 거의 512로 고정되어있다고 생각하면 될 듯
  Comments,     Trackbacks

IOCTL definitions for the SCSI scanner device driver
퍼옴
- http://kztechs.googlecode.com/svn/trunk/trunk/include/ntddk/inc/ddk/wlh/scsiscan.h
 


/****************************************************************************
*
*  (C) COPYRIGHT 1996-2000, MICROSOFT CORP.
*
*  FILE:        scsiscan.h
*
*  VERSION:     1.0
*
*  DATE:        2/11/1997
*
*  DESCRIPTION:
*    IOCTL definitions for the SCSI scanner device driver.
*
*****************************************************************************/

//
// Turns off []
//
#pragma warning(disable : 4200)

#ifndef _SCSISCAN_H_
#define _SCSISCAN_H_

// SCSISCAN_CMD.SrbFlags

#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER    0x00000008
#define SRB_FLAGS_DISABLE_AUTOSENSE         0x00000020
#define SRB_FLAGS_DATA_IN                   0x00000040
#define SRB_FLAGS_DATA_OUT                  0x00000080
#define SRB_FLAGS_NO_DATA_TRANSFER          0x00000000

// SCSISCAN_CMD.SrbStatus definitions

#define SRB_STATUS_PENDING                  0x00
#define SRB_STATUS_SUCCESS                  0x01
#define SRB_STATUS_ABORTED                  0x02
#define SRB_STATUS_ABORT_FAILED             0x03
#define SRB_STATUS_ERROR                    0x04
#define SRB_STATUS_BUSY                     0x05
#define SRB_STATUS_INVALID_REQUEST          0x06
#define SRB_STATUS_INVALID_PATH_ID          0x07
#define SRB_STATUS_NO_DEVICE                0x08
#define SRB_STATUS_TIMEOUT                  0x09
#define SRB_STATUS_SELECTION_TIMEOUT        0x0A
#define SRB_STATUS_COMMAND_TIMEOUT          0x0B
#define SRB_STATUS_MESSAGE_REJECTED         0x0D
#define SRB_STATUS_BUS_RESET                0x0E
#define SRB_STATUS_PARITY_ERROR             0x0F
#define SRB_STATUS_REQUEST_SENSE_FAILED     0x10
#define SRB_STATUS_NO_HBA                   0x11
#define SRB_STATUS_DATA_OVERRUN             0x12
#define SRB_STATUS_UNEXPECTED_BUS_FREE      0x13
#define SRB_STATUS_PHASE_SEQUENCE_FAILURE   0x14
#define SRB_STATUS_BAD_SRB_BLOCK_LENGTH     0x15
#define SRB_STATUS_REQUEST_FLUSHED          0x16
#define SRB_STATUS_INVALID_LUN              0x20
#define SRB_STATUS_INVALID_TARGET_ID        0x21
#define SRB_STATUS_BAD_FUNCTION             0x22
#define SRB_STATUS_ERROR_RECOVERY           0x23

#define SRB_STATUS_QUEUE_FROZEN             0x40
#define SRB_STATUS_AUTOSENSE_VALID          0x80

#define SRB_STATUS(Status) (Status & ~(SRB_STATUS_AUTOSENSE_VALID | SRB_STATUS_QUEUE_FROZEN))

typedef struct _SCSISCAN_CMD {
	ULONG   Reserved1;	
	ULONG   Size;
	ULONG   SrbFlags;				
	UCHAR   CdbLength;
	UCHAR   SenseLength;
	UCHAR	Reserved2;
	UCHAR	Reserved3;
	ULONG   TransferLength;
	UCHAR	Cdb[16];	
	PUCHAR  pSrbStatus;
	PUCHAR	pSenseBuffer;
} SCSISCAN_CMD, *PSCSISCAN_CMD;
	
// Temporarily set to 128. Should be determined by other definition.
#define MAX_STRING 128

typedef struct _SCSISCAN_INFO{
	ULONG   Size;
	ULONG   Flags;
    UCHAR   PortNumber;
    UCHAR   PathId;
    UCHAR   TargetId;
    UCHAR   Lun;
    UCHAR   AdapterName[MAX_STRING];
	ULONG   Reserved;
} SCSISCAN_INFO, *PSCSISCAN_INFO;

#define SCSISCAN_RESERVED         0x000
#define SCSISCAN_CMD_CODE         0x004
#define SCSISCAN_LOCKDEVICE       0x005
#define SCSISCAN_UNLOCKDEVICE     0x006
#define SCSISCAN_SET_TIMEOUT      0x007
#define SCSISCAN_GET_INFO         0x008

//---------------------------------------------------------------------------
// IOCTL definitions.
// Use these definitions when calling DeviceIoControl
//---------------------------------------------------------------------------
#define IOCTL_SCSISCAN_CMD		     CTL_CODE(FILE_DEVICE_SCANNER, SCSISCAN_CMD_CODE,	    METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
#define IOCTL_SCSISCAN_LOCKDEVICE    CTL_CODE(FILE_DEVICE_SCANNER, SCSISCAN_LOCKDEVICE,		METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
#define IOCTL_SCSISCAN_UNLOCKDEVICE  CTL_CODE(FILE_DEVICE_SCANNER, SCSISCAN_UNLOCKDEVICE,	METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
#define IOCTL_SCSISCAN_SET_TIMEOUT   CTL_CODE(FILE_DEVICE_SCANNER, SCSISCAN_SET_TIMEOUT,	METHOD_BUFFERED,   FILE_ANY_ACCESS)
#define IOCTL_SCSISCAN_GET_INFO      CTL_CODE(FILE_DEVICE_SCANNER, SCSISCAN_GET_INFO   ,	METHOD_OUT_DIRECT, FILE_ANY_ACCESS)

#endif


  Comments,     Trackbacks

IO_STACK_LOCATION defines (Major 함수별 파라미터)

Ref-

http://www.osronline.com/ddkx/kmarch/k112_49bm.htm


IO_STACK_LOCATION

The IO_STACK_LOCATION structure defines an I/O stack location, which is an entry in the I/O stack that is associated with each IRP. Each I/O stack location in an IRP has some common members and some request-type-specific members.

typedef struct _IO_STACK_LOCATION {
  UCHAR  MajorFunction;
  UCHAR  MinorFunction;
  UCHAR  Flags;
  UCHAR  Control;
  union {
        //
        // Parameters for IRP_MJ_CREATE 
        //
        struct {
            PIO_SECURITY_CONTEXT SecurityContext;
            ULONG Options;
            USHORT POINTER_ALIGNMENT FileAttributes;
            USHORT ShareAccess;
            ULONG POINTER_ALIGNMENT EaLength;
        } Create;
        //
        // Parameters for IRP_MJ_READ 
        //
        struct {
            ULONG Length;
            ULONG POINTER_ALIGNMENT Key;
            LARGE_INTEGER ByteOffset;
        } Read;
        //
        // Parameters for IRP_MJ_WRITE 
        //
        struct {
            ULONG Length;
            ULONG POINTER_ALIGNMENT Key;
            LARGE_INTEGER ByteOffset;
        } Write;
        //
        // Parameters for IRP_MJ_QUERY_INFORMATION 
        //
        struct {
            ULONG Length;
            FILE_INFORMATION_CLASS POINTER_ALIGNMENT FileInformationClass;
        } QueryFile;
        //
        // Parameters for IRP_MJ_SET_INFORMATION 
        //
        struct {
            ULONG Length;
            FILE_INFORMATION_CLASS POINTER_ALIGNMENT FileInformationClass;
            PFILE_OBJECT FileObject;
            union {
                struct {
                    BOOLEAN ReplaceIfExists;
                    BOOLEAN AdvanceOnly;
                };
                ULONG ClusterCount;
                HANDLE DeleteHandle;
            };
        } SetFile;
        //
        // Parameters for IRP_MJ_QUERY_VOLUME_INFORMATION 
        //
        struct {
            ULONG Length;
            FS_INFORMATION_CLASS POINTER_ALIGNMENT FsInformationClass;
        } QueryVolume;
        //
        // Parameters for IRP_MJ_DEVICE_CONTROL and IRP_MJ_INTERNAL_DEVICE_CONTROL 
        //
        struct {
            ULONG OutputBufferLength;
            ULONG POINTER_ALIGNMENT InputBufferLength;
            ULONG POINTER_ALIGNMENT IoControlCode;
            PVOID Type3InputBuffer;
        } DeviceIoControl;
        //
        // Nonsystem service parameters.
        //
        // Parameters for IRP_MN_MOUNT_VOLUME 
        //
        struct {
            PVOID DoNotUse1;
            PDEVICE_OBJECT DeviceObject;
        } MountVolume;
        //
        // Parameters for IRP_MN_VERIFY_VOLUME 
        //
        struct {
            PVOID DoNotUse1;
            PDEVICE_OBJECT DeviceObject;
        } VerifyVolume;
        //
        // Parameters for Scsi using IRP_MJ_INTERNAL_DEVICE_CONTROL 
        //
        struct {
            struct _SCSI_REQUEST_BLOCK *Srb;
        } Scsi;
        //
        // Parameters for IRP_MN_QUERY_DEVICE_RELATIONS 
        //
        struct {
            DEVICE_RELATION_TYPE Type;
        } QueryDeviceRelations;
        //
        // Parameters for IRP_MN_QUERY_INTERFACE 
        //
        struct {
            CONST GUID *InterfaceType;
            USHORT Size;
            USHORT Version;
            PINTERFACE Interface;
            PVOID InterfaceSpecificData;
        } QueryInterface;
        //
        // Parameters for IRP_MN_QUERY_CAPABILITIES 
        //
        struct {
            PDEVICE_CAPABILITIES Capabilities;
        } DeviceCapabilities;
        //
        // Parameters for IRP_MN_FILTER_RESOURCE_REQUIREMENTS 
        //
        struct {
            PIO_RESOURCE_REQUIREMENTS_LIST IoResourceRequirementList;
        } FilterResourceRequirements;
        //
        // Parameters for IRP_MN_READ_CONFIG and IRP_MN_WRITE_CONFIG 
        //
        struct {
            ULONG WhichSpace;
            PVOID Buffer;
            ULONG Offset;
            ULONG POINTER_ALIGNMENT Length;
        } ReadWriteConfig;
        //
        // Parameters for IRP_MN_SET_LOCK 
        //
        struct {
            BOOLEAN Lock;
        } SetLock;
        //
        // Parameters for IRP_MN_QUERY_ID 
        //
        struct {
            BUS_QUERY_ID_TYPE IdType;
        } QueryId;
        //
        // Parameters for IRP_MN_QUERY_DEVICE_TEXT 
        //
        struct {
            DEVICE_TEXT_TYPE DeviceTextType;
            LCID POINTER_ALIGNMENT LocaleId;
        } QueryDeviceText;
        //
        // Parameters for IRP_MN_DEVICE_USAGE_NOTIFICATION 
        //
        struct {
            BOOLEAN InPath;
            BOOLEAN Reserved[3];
            DEVICE_USAGE_NOTIFICATION_TYPE POINTER_ALIGNMENT Type;
        } UsageNotification;
        //
        // Parameters for IRP_MN_WAIT_WAKE 
        //
        struct {
            SYSTEM_POWER_STATE PowerState;
        } WaitWake;
        //
        // Parameter for IRP_MN_POWER_SEQUENCE 
        //
        struct {
            PPOWER_SEQUENCE PowerSequence;
        } PowerSequence;
        //
        // Parameters for IRP_MN_SET_POWER and IRP_MN_QUERY_POWER 
        //
        struct {
            ULONG SystemContext;
            POWER_STATE_TYPE POINTER_ALIGNMENT Type;
            POWER_STATE POINTER_ALIGNMENT State;
            POWER_ACTION POINTER_ALIGNMENT ShutdownType;
        } Power;
        //
        // Parameters for IRP_MN_START_DEVICE 
        //
        struct {
            PCM_RESOURCE_LIST AllocatedResources;
            PCM_RESOURCE_LIST AllocatedResourcesTranslated;
        } StartDevice;
        //
        // Parameters for WMI Minor IRPs 
        //
        struct {
            ULONG_PTR ProviderId;
            PVOID DataPath;
            ULONG BufferSize;
            PVOID Buffer;
        } WMI;
        //
        // Others - driver-specific
        //
        struct {
            PVOID Argument1;
            PVOID Argument2;
            PVOID Argument3;
            PVOID Argument4;
        } Others;
    } Parameters;
  PDEVICE_OBJECT  DeviceObject;
  PFILE_OBJECT  FileObject;
  .
  .
} IO_STACK_LOCATION, *PIO_STACK_LOCATION;

Members

MajorFunction
The IRP major function code indicating the type of I/O operation to be performed.
MinorFunction
A subfunction code for MajorFunction. The PnP Manager, the Power Manager, file system drivers, and SCSI class drivers set this member for some requests.
Flags
Request-type-specific values used almost exclusively by file system drivers. Removable-media device drivers check whether this member is set with SL_OVERRIDE_VERIFY_VOLUME for read requests to determine whether to continue the read operation even if the device object’s Flags is set with DO_VERIFY_VOLUME. Intermediate drivers layered over a removable-media device driver must copy this member into the I/O stack location of the next-lower driver in all incoming IRP_MJ_READ requests.
Control
Drivers can check this member to determine whether it is set with SL_PENDING_RETURNED. Drivers have read-only access to this member.
Parameters
A union that depends on the major and minor IRP function code values contained in MajorFunction and MinorFunction. For more information, see IRP Major Function Codes.
DeviceObject
A pointer to the driver-created DEVICE_OBJECT structure representing the target physical, logical, or virtual device for which this driver is to handle the IRP.
FileObject
A pointer to a FILE_OBJECT structure that represents the file object, if any, that is associated with DeviceObject pointer.

Headers

Defined in wdm.h and ntddk.h. Include wdm.h or ntddk.h.

Comments

For each IRP, there is one IO_STACK_LOCATION structure for each driver in a driver stack. Each IRP's set of I/O stack locations is appended to the IRP, following the IRP structure.

Every higher-level driver is responsible for setting up the I/O stack location for the next-lower driver in each IRP. A driver must callIoGetCurrentIrpStackLocation to get a pointer to its own stack location for each IRP. Higher-level drivers can callIoGetNextIrpStackLocation to get a pointer to the next-lower driver’s stack location.

The higher-level driver must set up the stack location contents before calling IoCallDriver to pass an IRP to the lower-level driver. If the driver will pass the input IRP on to the next lower-level driver, the dispatch routine should call IoSkipCurrentIrpStackLocation orIoCopyCurrentIrpStackLocationToNext to set up the I/O stack location of the next-lower driver.

A higher-level driver’s call to IoCallDriver sets the DeviceObject member to the next-lower-level driver’s target device object, in the I/O stack location of the lower driver. The I/O Manager passes each higher-level driver’s IoCompletion routine a pointer to its own device object when the IoCompletion routine is called on completion of the IRP.

If a higher-level driver allocates IRPs to make requests of its own, its IoCompletion routine is passed a NULL DeviceObject pointer if that driver neither allocates a stack location for itself nor sets up the DeviceObject pointer in its own stack location of the newly allocated IRP.

In some cases, a higher-level driver layered over a mass-storage device driver is responsible for splitting up large transfer requests for the underlying device driver. In particular, SCSI class drivers must check the Parameters.Read.Length and Parameters.Write.Length, determine whether the size of the requested transfer exceeds the underlying HBA’s transfer capabilities, and, if so, split the Length of the original request into a sequence of partial transfers to satisfy the original IRP.

  Comments,     Trackbacks

10byte CDB structure



아래는 명령이 WRITE(2A)일때 cdb구조


WRPROTECT가 001이면


WRPROTECT가 100이면

  Comments,     Trackbacks

SCSI REQUEST BLOCK의 CDB[0].OperationCode Commands
CDB[0] OperationCode 2A = Write

다음은 CDB에 들어가는 명령코드의 값과 행위.(나는 누구인가..여긴 또 어디인가...-_-)
List of SCSI commands
Code Command
00 TEST UNIT READY (mandatory)
01 RECALIBRATE or REWIND
03 REQUEST SENSE (mandatory except RBC)
04 FORMAT UNIT
05 READ BLOCK LIMITS
07 REASSIGN BLOCKS
07 INITIALIZE ELEMENT STATUS
08 READ (6)
0A WRITE (6)
0B SEEK (6)
0F READ REVERSE (6)
10 WRITE FILEMARKS (6)
11 SPACE (6)
12 INQUIRY (mandatory)
13 VERIFY(6)
14 RECOVER BUFFERED DATA
15 MODE SELECT (6)
16 RESERVE (6)
17 RELEASE (6)
18 COPY
19 ERASE (6)
1A MODE SENSE (6)
1B START/STOP UNIT
1B LOAD UNLOAD
1C RECEIVE DIAGNOSTIC RESULTS
1D SEND DIAGNOSTIC
1E PREVENT/ALLOW MEDIUM REMOVAL
23 READ FORMAT CAPACITIES (MMC)
24 SET WINDOW
25 READ CAPACITY (10)
28 READ (10)
29 READ GENERATION
2A WRITE (10)
2B SEEK (10)
2C ERASE (10)
2D READ UPDATED BLOCK
2E WRITE AND VERIFY (10)
2F VERIFY (10)
30 SEARCH DATA HIGH (10)
31 SEARCH DATA EQUAL (10)
32 SEARCH DATA LOW (10)
33 SET LIMITS (10)
34 PRE-FETCH (10)
35 SYNCHRONIZE CACHE (10)
36 LOCK/UNLOCK CACHE (10)
37 READ DEFECT DATA (10)
37 INITIALIZE ELEMENT STATUS WITH RANGE
38 MEDIUM SCAN
39 COMPARE
3A COPY AND VERIFY
3B WRITE BUFFER
3C READ BUFFER
3D UPDATE BLOCK
3E READ LONG
3F WRITE LONG
40 CHANGE DEFINITION
41 WRITE SAME (10)
44 REPORT DENSITY SUPPORT
45 PLAY AUDIO (10)
46 GET CONFIGURATION
47 PLAY AUDIO MSF
48 AUDIO TRACK INDEX (not mentioned in T10 overview)
49 AUDIO TRACK RELATIVE 10 (not mentioned in T10 overview)
4A GET EVENT STATUS NOTIFICATION
4B PAUSE / RESUME
4C LOG SELECT
4D LOG SENSE
50 XDWRITE (10)
51 XPWRITE (10) /*READ DISC INFORMATION CDB (in mmc5r02c 6.22.2)*/
52 XDREAD (10)
53 XDWRITEREAD (10)
54 SEND OPC INFORMATION
55 MODE SELECT (10)
56 RESERVE (10)
57 RELEASE (10)
58 REPAIR TRACK
5A MODE SENSE (10)
5B CLOSE TRACK / SESSION
5C READ BUFFER CAPACITY
5D SEND CUE SHEET
5E PERSISTENT RESERVE IN
5F PERSISTENT RESERVE OUT
7E EXTENDED CDB
7F VARIABLE LENGTH CDB
80 XDWRITE EXTENDED (16)
80 WRITE FILEMARKS (16)
81 REBUILD (16)
81 READ REVERSE (16)
82 REGENERATE (16)
83 EXTENDED COPY
84 RECEIVE COPY RESULTS
85 ATA COMMAND PASS THROUGH (16)
86 ACCESS CONTROL IN
87 ACCESS CONTROL OUT
88 READ (16)
89 COMPARE AND WRITE
8A WRITE (16)
8B ORWRITE
8C READ ATTRIBUTE
8D WRITE ATTRIBUTE
8E WRITE AND VERIFY (16)
8F VERIFY (16)
90 PRE-FETCH (16)
91 SYNCHRONIZE CACHE (16)
92 SPACE (16)
92 LOCK UNLOCK CACHE (16)
93 WRITE SAME (16)
9E SERVICE ACTION IN (16)
9F SERVICE ACTION OUT (16)
A0 REPORT LUNS
A1 ATA COMMAND PASS THROUGH (12)
A2 SECURITY PROTOCOL IN
A2 SEND EVENT (not mentioned in T10 overview)
A3 REPORT SUPPORTED OPCODES
A4 MAINTENANCE (OUT) (REPORT_KEY)
A5 MOVE MEDIUM
A5 PLAY AUDIO 12 (not mentioned in T10 overview)
A6 EXCHANGE MEDIUM
A7 MOVE MEDIUM ATTACHED
A8 READ (12)
A9 SERVICE ACTION OUT (12)
A9 AUDIO TRACK RELATIVE 12 (not mentioned in T10 overview)
AA WRITE (12)
AB SERVICE ACTION IN (12)
AC ERASE (12)
AD READ DVD STRUCTURE
AE WRITE AND VERIFY (12)
AF VERIFY (12)
B0 SEARCH DATA HIGH (12)
B1 SEARCH DATA EQUAL (12)
B2 SEARCH DATA LOW (12)
B3 SET LIMITS (12)
B4 READ ELEMENT STATUS ATTACHED
B5 SECURITY PROTOCOL OUT
B6 SEND VOLUME TAG
B7 READ DEFECT DATA (12)
B8 READ ELEMENT STATUS
B9 READ CD MSF
BA REDUNDANCY GROUP (IN)
BB REDUNDANCY GROUP (OUT)
BC SPARE (IN)
BC PLAY CD (not mentioned in T10 overview)
BD SPARE (OUT)
BE VOLUME SET (IN)
BF VOLUME SET (OUT)
  Comments,     Trackbacks

atapi object +74h hook

atapi object +74h hook
설명은 아래 참고~ 초짜라 시간 너무 오래거리네...;;

char __stdcall atapi_IdePortDispatch_HOOK_(PCWSTR Object, int f, int code, int addr)
{
  const WCHAR *v4; // eax@2
  char result; // al@3
  UNICODE_STRING DestinationString; // [sp+0h] [bp-8h]@1

  RtlInitUnicodeString(&DestinationString, Object);// object = \\Driver\\atapi
  if ( ObReferenceObjectByName(&DestinationString, 0x240u, 0, 0, IoDriverObjectType, 0, 0, &Object) >= 0//
                                                // ObReferenceObjectByName를 이용
                                                // 이름으로 DriverObject를 얻어온다.
                                                //
    && (ObfDereferenceObject(Object), v4 = &Object[2 * f + 28], *v4) )
  {
    *addr = *v4;                                // 74h = IRP_MJ_SCSI / IRP_MJ_INTERNAL_DEVICE_CONTROL
    *v4 = code;                                 // atapi의 Object를 얻어와서 IdePortDispatch부분을
                                                // 자신의 함수 부분으로 바꿈
                                                //
                                                // [0f] IRP_MJ_INTERNAL_DEVICE_CONTROL
                                                // f0e75a30   FileEngine+0x1a30 <<<<<<
    result = 1;
  }
  else
  {
    result = 0;
  }
  return result;
}

  Comments,     Trackbacks