api 리버싱 3 - RtlGetElementGenericTable

2015. 3. 7. 11:12Security ★ Development/Reversing

반응형

RtlGetElementGenericTable의 내용입니다.


MOV EBP, DWORD PTR SS : [EBP+8]

MOV EDX, DWORD PTR DS : [ECX+14]

MOV EAX, DWORD PTR DS : [ECX+C]

- EBP로 파라미터를 ECX에 넣고 14와 C오프셋의 값으로 각각 초기화하고 있습니다.


PUSH EBX

PUSH ESI

- EBX와 ESI의 값을 저장합니다.


MOV ESI, DWORD PTR [ECX+10]

PUSH EDI

MOV EDI, DWORD PTR [EBP+C]

- 10오프셋의 값을 ESI에 넣고 EDI값을 저장합니다.  그리고 EDI에 C 오프셋의 값을 넣습니다. EBP+8이 첫 번째 파라미터이니 +C는 두 번째 파라미터입니다.  


LEA EBX, DWORD PTR [EDI+1]

MOV DWORT PTR SS : [EBP+8], EBX

- EDI+1의 값을 EBX에 넣고 EBX의 값을 EBP+8위치로 옮깁니다.  


CMP EDI, -1

JE SHORT ntdll.778EB48

- EDI와 -1을 비교한 후 EDI == -1이면 함수 끝 부분인 778EB48 위치로 점프합니다.


CMP EBX, EDX

JA SHORT ntdll.778E2B48

CMP ESI, EBX

JNZ SHORT ntdll.778E2AF6

ADD EAX, 0C

JMP SHORT ntdll.778E2B4A

JBE SHORT ntdll.778E2B1A

- EBX와 EDX를 비교해서 EBX의 값이 더 크면 다시 종료합니다.  또한 JG가 아니라 JA를 사용했다는 것에서 EBX와 EDX의 값은 부호없는 정수라는 것을 알 수 있습니다.  그리고 ESI와 EBX를 비교하여 두 값이 같지 않으면 778E2AF6으로 점프합니다.  같으면 다음줄을 수행하는데 EAX에 0C의 값을 더하고 778E2BA4의 값으로 점프합니다.  이는 함수의 종료를 의미합니다.  JBE는 비교 결과가 작거나 같을 경우 점프하는 것인데 여기서는 바로 위 JNZ명령을 통해 진입하게 됩니다.

if(ESI!=EBX)

if(ESI<=EBX)

로 볼 수 있습니다.


MOV EDX, ESI

SHR EDX, 1

CMP EBX, EDX

JBE SHORT ntdll.778E2B0C

SUB ESI, EBX

JE SHORT ntdll.778E2B3D

- SHR은 오른쪽으로 1비트 이동하도록 하고 있습니다.  그리고 이 값이 EBX보다 작거나 같으면 778EB0C로 점프하며 그렇지 않으면 빼기를 수행한 후 같을 경우 778E2B3D로 이동합니다.  빼기 연산후 조건문은 빼기의 결과가 0일 경우 발생합니다.


DEC ESI

MOV EAX, DWORD PTR DS : [EAX+4]

JE SHORT ntdll.778E2B3D

JMP SHORT, ntdll.778E2B04

- ESI의 값을 1 감소시키고 EAX+4의 포이터를 EAX에 저장합니다.  a=a->b와 같은 리스트 사용법과 비슷합니다.  이 값이 같지 않으면 JMP명령을 통해 반복합니다.


LEA EAX, DWORD PTR DS : [ECX+4]

TEST EBX, EBX

JE SHORT ntdll.778E2B3D

DEC EBX

MOV EAX, DWORD PTR DS : [EAX]

JE SHORT ntdll.778E2B3D

JMP SHORT ntdll.778E2B13

- 분기문으로 인해 이 함수가 뭘 하는지 이렇게는 파악하기 어렵습니다.  후에 이 어셈블리 코드를 c 소스 코드로 정리할 것입니다.  지금은 일단 한줄 한줄 읽어 내려갑니다.  

TEST는 and연산을 수행하는 명령어입니다.  이를 통해 je명령을 수행합니다.  


MOV EDI, EBX

SUB EDX, EBX

SUB EDI, ESI

INC EDX

CMP EDI, EDX

JA SHORT ntdll.778E2B30

TEST EDI, EDI

JE SHORT ntdll.778E2B3D

DEC EDI

MOV EAX, DWORD PTR DS : [EAX]

JE SHORT ntdll.778E2B30

JMP SHORT ntdll.778E2B29

LEA EAX, DWORD PTR DS : [ECX+4]

TEST EDX, EDX

JE SHORT ntdll.778E2B3D

DEC EDX

MOV EAX, DWORD PTR DS : [EAX+4]

JNZ SHORT ntdll.778E2B37

MOV EDX, DWORT PTR SS : [EBP+8]

MOV DOWRD PTR DS : [ECX+C], EAX

MOV DWORD PTR DS : [ECX+10], EDX

JMP SHORT ntdll.778E2AF1

XOR EAX, EAX

POP EDI

POP ESI

POP EBX

POP EBP

RETN 8

- 처음 보는 명령어나 난해한 부분은 없습니다.  읽을 순 있어도 이렇게 보면 무슨 일을 하는지 알 수 없기 때문에 한줄 한줄 넘어갈 때마다 각 레지스터에 저장된 현재 값을 파악하고 있어야 합니다.  

지금까지 확인한 구조체의 내용입니다.

struct TABLE{    

UNKNOWN_PTR Member1;  

UNKNOWN_PTR Member2;  

UNKNOWN_PTR Member3;

LIST somelist;  //처음 EAX로 전달된 값을 이용해 while문을 돌려 list 검색을 합니다.  (검색 결과 리스트)  

ULONG someindex;  //함수의 2번째 파라미터와의 비교구문을 통해 어떤 인덱스라는 것을 알 수 있습니다.  (4번째 요소의 검색 인덱스)

ULONG NumberOfElements; 

UNKNOWN Member7;

UNKNOWN Member8;

UNKNOWN Member9;

UNKNOWN Member10;

}


처음 리버싱 할 때에는 아래와 같이 어셈블리 코드를 따라가며 소스코드를 추출해 보는 것이 도움이 됩니다.