Entwickler-Ecke

Windows API - From C to Pascal


mohfa - So 21.02.10 14:51
Titel: From C to Pascal
Please can someone convert this from C to Pascal :


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
259:
260:
261:
262:
263:
264:
265:
266:
267:
268:
269:
270:
271:
272:
273:
274:
275:
276:
277:
278:
279:
280:
281:
282:
283:
284:
285:
286:
287:
288:
289:
290:
291:
292:
293:
294:
295:
296:
297:
298:
299:
300:
301:
302:
303:
304:
305:
306:
307:
308:
309:
310:
311:
312:
313:
314:
315:
316:
317:
318:
319:
320:
321:
322:
323:
324:
325:
326:
327:
328:
329:
330:
331:
332:
333:
334:
335:
336:
337:
338:
339:
340:
341:
342:
343:
344:
345:
346:
347:
348:
349:
350:
351:
352:
353:
354:
355:
356:
357:
358:
359:
360:
361:
362:
363:
364:
365:
366:
367:
368:
369:
370:
371:
372:
373:
374:
375:
376:
377:
378:
379:
380:
381:
382:
383:
384:
385:
386:
387:
388:
389:
390:
391:
392:
393:
394:
395:
396:
397:
398:
399:
400:
401:
402:
403:
404:
405:
406:
407:
408:
409:
410:
411:
412:
413:
414:
415:
416:
417:
418:
419:
420:
421:
422:
423:
424:
425:
426:
  /*

  EPOS - Heuristic Entry-point Obscuring (Virus) Scanner 
  and Win32. CTX.Phage disinfector

  by Piotr Bania <bania.piotr@gmail.com>
  http://www.piotrbania.com

  

  */



#include    <stdio.h>
#include    <stdlib.h>
#include    <conio.h>
#include    <windows.h>



#define      O_CALL      0xE8  
#define      O_JMP      0xE9


#define      TEMP_FILE_NAME  "C:\_$temp.vir"


void      scan_file(char *name);
bool      try_disinfect(char *name, DWORD where_ctx, DWORD caller, DWORD upa, DWORD sv);




int  main(int argc, char *argv[]) {

  printf("---------------------------------------------------------------------------\n");
  printf("                  EPO-SCANNER - (c) Piotr Bania\n");
  printf("                   http://pb.specialised.info\n");
  printf("---------------------------------------------------------------------------\n");

  if (argc<2
  {
    printf("[!] Usage: EPO-s.exe <file>\n");
    printf("[!] Press any key to exit.\n");
    getch();
    return 0;
  }

  printf("[+] Trying to scan: %s\n",argv[1]);
  scan_file(argv[1]);
  
  return 0;
}


void scan_file(char *name) {
  HANDLE file,map;
  void* mymap;
  DWORD startrange = NULL, endrange = NULL, i = NULL, loc = NULL, temp_loc = NULL, upa = NULL;
  DWORD where_ctx = NULL,caller = NULL, sv = NULL;
  PIMAGE_DOS_HEADER pMZ = NULL;
  PIMAGE_NT_HEADERS pPE = NULL;
  PIMAGE_SECTION_HEADER pSH = NULL,pSHC = NULL;
  char *temp_name = TEMP_FILE_NAME;
  WORD sections;
  int count=0;
  

  if (!CopyFile(name,temp_name,FALSE)) 
  {
    printf("[-] Error: copying file failed - no future disinfection possible, error: %d\n",GetLastError());
  }

  
  if ((file = CreateFile(name,GENERIC_READ | FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL)) == INVALID_HANDLE_VALUE) 
  {
    printf("[-] Error: Cannot open file - error: %d\n",GetLastError());
    goto error_mode1;
  }

  if ((map = CreateFileMapping(file,NULL,PAGE_READWRITE | SEC_COMMIT,NULL,NULL,NULL)) == NULL) 
  {
    printf("[-] Error: Cannot create map of file - error: %d\n",GetLastError());
    goto error_mode2;
  }

  if ((mymap = MapViewOfFile(map,FILE_MAP_ALL_ACCESS,NULL,NULL,NULL)) == NULL) 
  {
    printf("[-] Error: Cannot create map view of file - error: %d\n",GetLastError());
    goto error_mode3;
  }

  pMZ=(PIMAGE_DOS_HEADER) mymap;

  if (pMZ->e_magic != IMAGE_DOS_SIGNATURE) 
  {
    printf("[-] Error: Bad MZ signature\n");
    goto error_mode4;
  }

  pPE=(PIMAGE_NT_HEADERS) ((DWORD)mymap + pMZ->e_lfanew);

  if (IsBadReadPtr((VOID*)pPE,sizeof(PIMAGE_NT_HEADERS)) == TRUE) 
  {
    printf("[-] Error: Bad PE file\n");
    goto error_mode4;
  }

  if (pPE->Signature != IMAGE_NT_SIGNATURE || pPE->FileHeader.NumberOfSections == NULL) 
  {
    printf("[-] Error: Bad PE file\n");
    goto error_mode4;
  }

  if (pPE->OptionalHeader.ImageBase <= 0 || pPE->OptionalHeader.AddressOfEntryPoint <= 0 || pPE->FileHeader.NumberOfSections <= 0
  {
    printf("[-] Error: Bad PE file\n");
    goto error_mode4;
  }

  printf("[+] Imagebase: 0x%.08x - Entrypoint: 0x%.08x (0x%.08x)\n",pPE->OptionalHeader.ImageBase,pPE->OptionalHeader.AddressOfEntryPoint,pPE->OptionalHeader.ImageBase+pPE->OptionalHeader.AddressOfEntryPoint);

  sections = pPE->FileHeader.NumberOfSections;
  pSH = (PIMAGE_SECTION_HEADER)((DWORD)mymap+pMZ->e_lfanew + sizeof(IMAGE_NT_HEADERS));
  
  
  while (sections != 0
  {
    if (IsBadReadPtr(&pSH,sizeof(PIMAGE_SECTION_HEADER)) == TRUE) 
    {
      printf("[-] Error: Bad PE file\n");
      goto error_mode4;
    }

    char *secname=(char *) pSH->Name;
    if (secname == NULL) strcpy(secname,"NONAME");

    startrange=(DWORD) pSH->VirtualAddress + pPE->OptionalHeader.ImageBase;
    endrange=(DWORD) startrange + pSH->Misc.VirtualSize;

    if (startrange <=0 || startrange <= pPE->OptionalHeader.ImageBase || endrange <=0 || pPE->OptionalHeader.ImageBase <= 0 || pSH->Misc.PhysicalAddress < 0 || pSH->SizeOfRawData < 0
    {
      printf("[-] Error: The %s section is broken\n",secname);
      goto error_mode4;
    }

    if (pSH->VirtualAddress <= pPE->OptionalHeader.AddressOfEntryPoint && pPE->OptionalHeader.AddressOfEntryPoint < pSH->VirtualAddress + pSH->Misc.VirtualSize) 
    {
      printf("[+] Checking call/jump requests from %s section (EP)\n",secname);
      pSHC = pSH;
    }

  
    pSH++;
    sections--;
  }

  pSH--;
  
  if (pSHC == NULL) 
  {
    printf("[-] Error: invalid entrypoint\n");
    goto error_mode4;
  }


  printf("[+] Starting heuristics scan on %s section...\n\n",pSHC->Name);

  if (pSHC == pSH) 
  {
    printf("[!] Alert: Entrypoint points to last section (%s) -> 0x%.08x\n",pSH->Name,pPE->OptionalHeader.AddressOfEntryPoint + pPE->OptionalHeader.ImageBase);
    printf("[!] Alert: The file may be infected!\n");
    printf("[+] No deep-scan action was performed\n");
    goto error_mode4;
  }


  printf("[+] Starting from offset: 0x%.08x\n",pPE->OptionalHeader.ImageBase + pSHC->VirtualAddress);

  for (i = 0; (i != pSHC->SizeOfRawData); i++) 
  {
    loc = (DWORD)((DWORD)mymap + pSHC->PointerToRawData) + i;
    
    if ((*(BYTE*)loc) == O_CALL || (*(BYTE*)loc) == O_JMP ) 
    {
      loc++;
      temp_loc = (DWORD)((DWORD)pSHC->VirtualAddress + i + (*(DWORD*)loc)) + 5;
    
      if (temp_loc >= pSH->VirtualAddress && temp_loc <= pSH->VirtualAddress + pSH->Misc.VirtualSize) 
      {
        printf("[!] Alert: Detected request to %s(0x%.08x) section at: 0x%.08x\n",pSH->Name,pPE->OptionalHeader.ImageBase + temp_loc, pSHC->VirtualAddress + pPE->OptionalHeader.ImageBase + i);
        if (where_ctx == NULL) 
        {
          where_ctx = (DWORD)(pPE->OptionalHeader.ImageBase + temp_loc);
          caller = (DWORD)(pSHC->VirtualAddress + pPE->OptionalHeader.ImageBase + i);
          upa = (DWORD)(pSH->VirtualAddress + pPE->OptionalHeader.ImageBase);
          sv = loc - 1;
          
        }
        count++;
      }
      loc--;
    }

  }
  
  printf("[+] Scan finished, %d suspected instruction(s) found.\n",count);
  if (count != 0
  {
    printf("[!] Warning: the file may be infected!\n");
    printf("\n[?] Do you want to try dis-infect the file?\n");
    printf("[?] Warning: the file may be executed if this is not the CTX.Phage\n");
    printf("    infection.\n");
    printf("[?] Disinfect: (y)es / (n)o  ? \n");

    if (getch() == 'y') try_disinfect(name, where_ctx, caller, upa, sv);
    

  }

  error_mode4:
    UnmapViewOfFile(mymap);

  error_mode3:
    CloseHandle(map);
    
  error_mode2:
    CloseHandle(file);

  error_mode1:
    DeleteFile(temp_name);

}


bool try_disinfect(char *name, DWORD where_ctx, DWORD caller, DWORD upa, DWORD sv) {
  STARTUPINFO si;
  PROCESS_INFORMATION pi;
  CONTEXT tc;
  DEBUG_EVENT de;
  DWORD stack_v = NULL, _GetProcAddress = NULL, oldp;
  unsigned char patch[4] = { 0x900x900xCC };
  unsigned char ctx_sig[15] = { 0x6A0x000x6A0x050xE80x050x000x000x000x900x900x900x900x900x50 };
  unsigned char ctx_fly[15];
  char *temp_name = TEMP_FILE_NAME;
  int fe=NULL, found=NULL;
  

  _GetProcAddress = (DWORD) GetProcAddress(LoadLibrary("KERNEL32.DLL"), "GetProcAddress");


  GetStartupInfo(&si);
  if (!CreateProcess(NULL,temp_name,NULL,NULL,FALSE,DEBUG_PROCESS + DEBUG_ONLY_THIS_PROCESS, NULL, NULL, &si, &pi)) 
  {
    printf("[-] Error: cannot create process, error: %d\n",GetLastError());
    goto error_di;
  }

  printf("\n[+] Process created, pid=0x%.08x\n",pi.dwProcessId);
  printf("[+] Starting emulation engine...\n");
  

  while (1
  {
    WaitForDebugEvent(&de,INFINITE);
    if (de.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) {
      printf("[!] Error: ups process exited...\n");
      goto error_term;
    }

    if (de.dwDebugEventCode == EXCEPTION_DEBUG_EVENT) 
    {
      if (de.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
        if (de.u.Exception.dwFirstChance == TRUE) 
        {
          printf("[+] Exception occured at: 0x%.08x, passing to program.\n",de.u.Exception.ExceptionRecord.ExceptionAddress);
          ContinueDebugEvent(de.dwProcessId,de.dwThreadId,DBG_EXCEPTION_NOT_HANDLED);
        }
        else 
        {
          printf("[-] Hard error occured, terminating the program\n");
          printf("[-] Disinfecting failed\n");
          goto error_term;
        }

      }





      if (de.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT) 
      {

        if (fe == NULL) 
        {
          fe = 1;
          printf("[+] Reached break point at 0x%.08x\n",de.u.Exception.ExceptionRecord.ExceptionAddress);
          printf("[+] Modifing 4 bytes at host stack\n");
          

          tc.ContextFlags = CONTEXT_CONTROL;
          if (!GetThreadContext(pi.hThread, &tc)) 
          {
            printf("[-] Failed to get thread context, error: %d\n",GetLastError());
            printf("[-] Disinfecting failed\n");
            goto error_term;
          }

          ReadProcessMemory(pi.hProcess, (void*)tc.Esp, &stack_v,4,NULL);

          if (stack_v == NULL) 
          {
            printf("[-] Error: reading from stack failed\n");
            printf("[-] Disinfecting failed\n");
            goto error_term;
          }

          tc.Esp = tc.Esp - 4;
          caller += 5;

          if (!WriteProcessMemory(pi.hProcess, (void*)tc.Esp, &caller, 4, NULL)) 
          {
            printf("[-] Error: writing to stack failed\n");
            printf("[-] Disinfecting failed\n");
            goto error_term;
          }
          printf("[+] Stack modified, 0x%.08x added caller -> 0x%.08x\n",tc.Esp, caller);

          printf("[+] Redirecting EIP to 0x%.08x...\n",where_ctx);
          tc.Eip = where_ctx;

          if (!SetThreadContext(pi.hThread, &tc)) 
          {
            printf("[-] Failed to set thread context, error: %d\n",GetLastError());
            printf("[-] Disinfecting failed\n");
            goto error_term;
          
          }

          VirtualProtectEx(pi.hProcess, (void*) _GetProcAddress, sizeof(patch), PAGE_READWRITE, &oldp);
          WriteProcessMemory(pi.hProcess, (void*) _GetProcAddress, &patch, sizeof(patch), NULL);
          VirtualProtectEx(pi.hProcess, (void*) _GetProcAddress, sizeof(patch), oldp, &oldp);

          printf("[+] Placed breaker at 0x%.08x\n",_GetProcAddress);

          ContinueDebugEvent(de.dwProcessId,de.dwThreadId,DBG_CONTINUE);
        }
      
      
          if ((DWORD) de.u.Exception.ExceptionRecord.ExceptionAddress > _GetProcAddress && (DWORD) de.u.Exception.ExceptionRecord.ExceptionAddress < _GetProcAddress + sizeof(patch)) 
          {
          printf("[+] Virus reached the breaker at 0x%.08x\n",de.u.Exception.ExceptionRecord.ExceptionAddress);
          

          tc.ContextFlags = CONTEXT_CONTROL;
          if (!GetThreadContext(pi.hThread, &tc)) 
          {
            printf("[-] Failed to get thread context, error: %d\n",GetLastError());
            printf("[-] Disinfecting failed\n");
            goto error_term;
          }
          
          ReadProcessMemory(pi.hProcess, (void*)tc.Esp, &stack_v, 4, NULL);
          printf("[+] Virus request captured from 0x%.08x\n",stack_v);
          printf("[+] Scanning backwards to 0x%.08x\n",upa);
        

          while (1
          {
            if (!ReadProcessMemory(pi.hProcess, (void*)stack_v, &ctx_fly, sizeof(ctx_sig), NULL)) break;
            if (stack_v <= upa) break;
            
            found = 1;
            for (int ii=0; ii < sizeof(ctx_sig); ii++) 
            {
              if (ctx_sig[ii] != ctx_fly[ii]) 
              {
                if (ctx_sig[ii] != 0x90
                {
                  found = 0;
                  break;
                }
              }
            }
            
            if (found == 1
            {
              printf("[+] Orginal bytes were found at 0x%.08x\n",stack_v + 9);
              printf("[!] Repairing the broken instruction.\n");
              ReadProcessMemory(pi.hProcess, (void*)(stack_v + 9), (void*) sv, 5, NULL);
              printf("[!] The file was disinfected!\n");
              getch();
              goto error_term;
            }

            stack_v--;
          }

          if (found == 0
          {
            printf("[-] Error: no signature was found.\n");
            printf("[-] Disinfecting failed\n");
            goto error_term;
          }

          goto error_term;
        }
            
      }

    }


    ContinueDebugEvent(de.dwProcessId,de.dwThreadId,DBG_EXCEPTION_NOT_HANDLED);

  }


  error_term:
    TerminateProcess(pi.hProcess,NULL);

  error_di:
    return TRUE;

}



thank you all

Moderiert von user profile iconNarses: Code- durch C#-Tags ersetzt


BenBE - So 21.02.10 15:09

user profile iconmohfa hat folgendes geschrieben Zum zitierten Posting springen:
Please can someone convert this from C to Pascal :

Yes, someone sure can. [http://homepages.tesco.net/~J.deBoynePollard/FGA/questions-with-yes-or-no-answers.html]


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
{

  EPOS - Heuristic Entry-point Obscuring (Virus) Scanner 
  and Win32. CTX.Phage disinfector

  by Piotr Bania <bania.piotr@gmail.com>
  http://www.piotrbania.com

  Ported by BenBE

}

program EPOS;
{$APPTYPE CONSOLE}

//#include    <stdio.h>
//#include    <stdlib.h>
//#include    <conio.h>
//#include    <windows.h>
uses Windows;

//#define      O_CALL      0xE8  
//#define      O_JMP      0xE9
const
    O_CALL              = $E8;
    O_JMP               = $E9;

//#define      TEMP_FILE_NAME  "C:\_$temp.vir"
const
    TEMP_FILE_NAME  = 'C:\_$temp.vir';

//void      scan_file(char *name);
procedrue scan_file(name: String); forward;
//bool      try_disinfect(char *name, DWORD where_ctx, DWORD caller, DWORD upa, DWORD sv);
function try_disinfect(name: String; where_ctx: DWORD; caller: DWORD; upa: DWORD; sv: DWORD): Boolean; forward;

//int  main(int argc, char *argv[]) {
procedure main; //Normally this would go into the begin...end.-Block in Delphi
begin

//  printf("---------------------------------------------------------------------------\n");
//  printf("                  EPO-SCANNER - (c) Piotr Bania\n");
//  printf("                   http://pb.specialised.info\n");
//  printf("---------------------------------------------------------------------------\n");
  WriteLn('---------------------------------------------------------------------------');
  WriteLn('                  EPO-SCANNER - (c) Piotr Bania');
  WriteLn('                   http://pb.specialised.info');
  WriteLn('---------------------------------------------------------------------------');

//  if (argc<2) 
//  {
  if ParamCount < 2 Then
  begin
//    printf("[!] Usage: EPO-s.exe <file>\n");
//    printf("[!] Press any key to exit.\n");
//    getch();
//    return 0;
    WriteLn('[!] Usage: EPO-s.exe <file>');
    WriteLn('[!] Press any key to exit.');
    ReadLn; //Waits for Return instead of any key
    Exit;
//  }
  end;

//  printf("[+] Trying to scan: %s\n",argv[1]);
//  scan_file(argv[1]);
  WirteLn(Format('[+] Trying to scan: %s',[ParamStr(1)]));
  scan_file(ParamStr(1));
  
//  return 0;
//Not needed here; but could be set using SetExitStatus

//}
end;

{...}


hmmm, the rest follows later ... You can mainly port this 1:1 ...


FinnO - So 21.02.10 15:16

BenBE hat folgendes geschrieben:
the rest follows later


:rofl: never thought this to be correct :D


BenBE - So 21.02.10 15:20

user profile iconFinnO hat folgendes geschrieben Zum zitierten Posting springen:
BenBE hat folgendes geschrieben:
the rest follows later


:rofl: hätte nie gedacht, dass das richtig ist... :D

Asked Westerwave and Oettinger ... And they both agreed on this to be correct :mrgreen: Especially since Leo seconds me on this one ;-)


FinnO - So 21.02.10 15:25

nevertheless i think it's bad style^^


mohfa - So 21.02.10 15:27

Hoooooollla BenBE .many thanks

please Go On with rest of the code ..... :)


jaenicke - So 21.02.10 15:27

user profile iconFinnO hat folgendes geschrieben Zum zitierten Posting springen:
:rofl: hätte nie gedacht, dass das richtig ist... :D
Well then go to the kindergarten and have a look at the rucksacks. :mrgreen:

But I think that's enough off topic for now. ;-)


BenBE - So 21.02.10 15:29

@user profile iconFinnO: At least be of some help and translate one of the other functions I left for the smartasses ;-)

user profile iconmohfa hat folgendes geschrieben Zum zitierten Posting springen:
please Go On with rest of the code ..... :)

Do you get the basic idea on how to port things?


mohfa - So 21.02.10 15:34

yes normally .... :roll:


FinnO - So 21.02.10 15:38

I won't translate anything including "GoTo"


mohfa - So 21.02.10 15:44

ok Then translate only this part :


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
  for (i = 0; (i != pSHC->SizeOfRawData); i++) 
  {
    loc = (DWORD)((DWORD)mymap + pSHC->PointerToRawData) + i;
    
    if ((*(BYTE*)loc) == O_CALL || (*(BYTE*)loc) == O_JMP ) 
    {
      loc++;
      temp_loc = (DWORD)((DWORD)pSHC->VirtualAddress + i + (*(DWORD*)loc)) + 5;
    
      if (temp_loc >= pSH->VirtualAddress && temp_loc <= pSH->VirtualAddress + pSH->Misc.VirtualSize) 
      {
        printf("[!] Alert: Detected request to %s(0x%.08x) section at: 0x%.08x\n",pSH->Name,pPE->OptionalHeader.ImageBase + temp_loc, pSHC->VirtualAddress + pPE->OptionalHeader.ImageBase + i);
        if (where_ctx == NULL) 
        {
          where_ctx = (DWORD)(pPE->OptionalHeader.ImageBase + temp_loc);
          caller = (DWORD)(pSHC->VirtualAddress + pPE->OptionalHeader.ImageBase + i);
          upa = (DWORD)(pSH->VirtualAddress + pPE->OptionalHeader.ImageBase);
          sv = loc - 1;
          
        }
        count++;
      }

      loc--;
    }

  }


of course excluding the ' GOTO '.

and i will do the rest .

thank you in advance .

Moderiert von user profile iconNarses: Code- durch C#-Tags ersetzt


BenBE - So 21.02.10 16:17


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
//void scan_file(char *name) {
procedure scan_file(name: string);
var
//  HANDLE file,map;
  file, map: THandle; //Actually this is HFile, but this doesn't really matter here
//  void* mymap;
  mymap: Pointer;
//  DWORD startrange = NULL, endrange = NULL, i = NULL, loc = NULL, temp_loc = NULL, upa = NULL;
  startrange, endrange, i, loc, temp_loc, upa: DWORD; //No inline initialization for local variables allowed in Delphi
//  DWORD where_ctx = NULL,caller = NULL, sv = NULL;
  where_ctx, caller, sv: DWORD; //Same goes here ...
//  PIMAGE_DOS_HEADER pMZ = NULL;
  pMZ: PIMAGE_DOS_HEADER;
//  PIMAGE_NT_HEADERS pPE = NULL;
  pPE: PIMAGE_NT_HEADERS;
//  PIMAGE_SECTION_HEADER pSH = NULL,pSHC = NULL;
  pSH, pSHC: PIMAGE_SECTION_HEADER;
//  char *temp_name = TEMP_FILE_NAME;
  temp_name: String;
//  WORD sections;
  sections: WORD;
//  int count=0;
  count: Integer;
label  //Usually those labels here should be translated as resource protection blocks with try-finally.
  error_mode1, error_mode2, error_mode3, error_mode4;
begin
  startrange := 0;
  endrange := 0;
  i := 0;
  loc := 0;
  temp_loc := 0;
  upa := 0;
  where_ctx := 0;
  caller := 0;
  sv := 0;
  pMZ := nil;
  pPE := nil;
  pSH := nil;
  pSHC := nil;
  temp_name := TEMP_FILE_NAME;

//  if (!CopyFile(name,temp_name,FALSE)) 
  if not CopyFile(name,temp_name,FALSE) then
//  {
  begin
//    printf("[-] Error: copying file failed - no future disinfection possible, error: %d\n",GetLastError());
    WriteLn(Format('[-] Error: copying file failed - no future disinfection possible, error: %d', [GetLastError()]));
//  }
  end;
  
//  if ((file = CreateFile(name,GENERIC_READ | FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL)) == INVALID_HANDLE_VALUE) 
  file := CreateFile(name, GENERIC_READ or FILE_SHARE_READ or FILE_SHARE_WRITE, nilnil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nil);
  if file = INVALID_HANDLE_VALUE then
//  {
  begin
//    printf("[-] Error: Cannot open file - error: %d\n",GetLastError());
//    goto error_mode1;
    WriteLn(Format('[-] Error: Cannot open file - error: %d',[GetLastError()]));
    goto error_mode1;
//  }
  end;

//  if ((map = CreateFileMapping(file,NULL,PAGE_READWRITE | SEC_COMMIT,NULL,NULL,NULL)) == NULL) 
  map := CreateFileMapping(filenil, PAGE_READWRITE or SEC_COMMIT, nilnilnil);
  if map = 0 then
//  {
  begin
//    printf("[-] Error: Cannot create map of file - error: %d\n",GetLastError());
//    goto error_mode2;
    WriteLn(Format('[-] Error: Cannot create map of file - error: %d',[GetLastError()]));
    goto error_mode2;
//  }
  end;

//  if ((mymap = MapViewOfFile(map,FILE_MAP_ALL_ACCESS,NULL,NULL,NULL)) == NULL) 
  mymap := MapViewOfFile(map,FILE_MAP_ALL_ACCESS,nil,nil,nil);
  if mymap = nil then 
//  {
  begin
    printf("[-] Error: Cannot create map view of file - error: %d\n",GetLastError());
    goto error_mode3;
//  }
  end;

//  pMZ=(PIMAGE_DOS_HEADER) mymap;
  pMZ := PIMAGE_DOS_HEADER(mymap);

//  if (pMZ->e_magic != IMAGE_DOS_SIGNATURE) 
  if pMZ^.e_magic <> IMAGE_DOS_SIGNATURE then
//  {
  begin
//    printf("[-] Error: Bad MZ signature\n");
//    goto error_mode4;
    WriteLn('[-] Error: Bad MZ signature');
    goto error_mode4;
//  }
  end;

//  pPE=(PIMAGE_NT_HEADERS) ((DWORD)mymap + pMZ->e_lfanew);
  pPE := PIMAGE_NT_HEADERS(DWORD(mymap) + pMZ^.e_lfanew);

//  if (IsBadReadPtr((VOID*)pPE,sizeof(PIMAGE_NT_HEADERS)) == TRUE) 
  if IsBadReadPtr(pPE, sizeof(TIMAGE_NT_HEADERS)) then //DON'T EVER COMPARE BOOLEANS AGAINST CONSTANTS!
//  {
  begin
//    printf("[-] Error: Bad PE file\n");
//    goto error_mode4;
    WriteLn('[-] Error: Bad PE file');
    goto error_mode4;
//  }
  end;

//  if (pPE->Signature != IMAGE_NT_SIGNATURE || pPE->FileHeader.NumberOfSections == NULL) 
  if (pPE^.Signature <> IMAGE_NT_SIGNATURE) or (pPE^.FileHeader.NumberOfSections = 0then
//  {
  begin
//    printf("[-] Error: Bad PE file\n");
//    goto error_mode4;
    WriteLn('[-] Error: Bad PE file');
    goto error_mode4;
//  }
  end;

//  if (pPE->OptionalHeader.ImageBase <= 0 || pPE->OptionalHeader.AddressOfEntryPoint <= 0 || pPE->FileHeader.NumberOfSections <= 0) 
  if (pPE^.OptionalHeader.ImageBase <= 0or (pPE^.OptionalHeader.AddressOfEntryPoint <= 0or (pPE^.FileHeader.NumberOfSections <= 0then
//  {
  begin
    printf("[-] Error: Bad PE file\n");
    goto error_mode4;
//  }
  end;

//  printf("[+] Imagebase: 0x%.08x - Entrypoint: 0x%.08x (0x%.08x)\n",pPE->OptionalHeader.ImageBase,pPE->OptionalHeader.AddressOfEntryPoint,pPE->OptionalHeader.ImageBase+pPE->OptionalHeader.AddressOfEntryPoint);
  WriteLn(Format('[+] Imagebase: 0x%.08x - Entrypoint: 0x%.08x (0x%.08x)\n', [pPE^.OptionalHeader.ImageBase, pPE^.OptionalHeader.AddressOfEntryPoint, pPE^.OptionalHeader.ImageBase + pPE^.OptionalHeader.AddressOfEntryPoint]));

//  sections = pPE->FileHeader.NumberOfSections;
//  pSH = (PIMAGE_SECTION_HEADER)((DWORD)mymap+pMZ->e_lfanew + sizeof(IMAGE_NT_HEADERS));
  sections := pPE^.FileHeader.NumberOfSections;
  pSH := PIMAGE_SECTION_HEADER(DWORD(mymap)+pMZ^.e_lfanew + sizeof(IMAGE_NT_HEADERS));

(* //I drop this section for someone else ...
  while (sections != 0) 
  {
    if (IsBadReadPtr(&pSH,sizeof(PIMAGE_SECTION_HEADER)) == TRUE) 
    {
      printf("[-] Error: Bad PE file\n");
      goto error_mode4;
    }

    char *secname=(char *)
 pSH->Name;
    if (secname == NULL) strcpy(secname,"NONAME");

    startrange=(DWORD) pSH->VirtualAddress + pPE->OptionalHeader.ImageBase;
    endrange=(DWORD) startrange + pSH->Misc.VirtualSize;

    if (startrange <=0 || startrange <= pPE->OptionalHeader.ImageBase || endrange <=0 || pPE->OptionalHeader.ImageBase <= 0 || pSH->Misc.PhysicalAddress < 0 || pSH->SizeOfRawData < 0
    {
      printf("[-] Error: The %s section is broken\n",secname);
      goto error_mode4;
    }


    if (pSH->VirtualAddress <= pPE->OptionalHeader.AddressOfEntryPoint && pPE->OptionalHeader.AddressOfEntryPoint < pSH->VirtualAddress + pSH->Misc.VirtualSize) 
    {
      printf("[+] Checking call/jump requests from %s section (EP)\n",secname);
      pSHC = pSH;
    }


  
    pSH++;
    sections--;
  }

  pSH--;
  
  if (pSHC == NULL) 
  {
    printf("[-] Error: invalid entrypoint\n");
    goto error_mode4;
  }



  printf("[+] Starting heuristics scan on %s section...\n\n",pSHC->Name);

  if (pSHC == pSH) 
  {
    printf("[!] Alert: Entrypoint points to last section (%s) -> 0x%.08x\n",pSH->Name,pPE->OptionalHeader.AddressOfEntryPoint + pPE->OptionalHeader.ImageBase);
    printf("[!] Alert: The file may be infected!\n");
    printf("[+] No deep-scan action was performed\n");
    goto error_mode4;
  }



  printf("[+] Starting from offset: 0x%.08x\n",pPE->OptionalHeader.ImageBase + pSHC->VirtualAddress);

  for (i = 0; (i != pSHC->SizeOfRawData); i++) 
  {
    loc = (DWORD)((DWORD)mymap + pSHC->PointerToRawData) + i;
    
    if ((*(BYTE*)loc) == O_CALL || (*(BYTE*)loc) == O_JMP ) 
    {
      loc++;
      temp_loc = (DWORD)((DWORD)pSHC->VirtualAddress + i + (*(DWORD*)loc)) + 5;
    
      if (temp_loc >= pSH->VirtualAddress && temp_loc <= pSH->VirtualAddress + pSH->Misc.VirtualSize) 
      {
        printf("[!] Alert: Detected request to %s(0x%.08x) section at: 0x%.08x\n",pSH->Name,pPE->OptionalHeader.ImageBase + temp_loc, pSHC->VirtualAddress + pPE->OptionalHeader.ImageBase + i);
        if (where_ctx == NULL) 
        {
          where_ctx = (DWORD)(pPE->OptionalHeader.ImageBase + temp_loc);
          caller = (DWORD)(pSHC->VirtualAddress + pPE->OptionalHeader.ImageBase + i);
          upa = (DWORD)(pSH->VirtualAddress + pPE->OptionalHeader.ImageBase);
          sv = loc - 1;
          
        }

        count++;
      }
      loc--;
    }

  }
  
  printf("[+] Scan finished, %d suspected instruction(s) found.\n",count);
  if (count != 0
  {
    printf("[!] Warning: the file may be infected!\n");
    printf("\n[?] Do you want to try dis-infect the file?\n");
    printf("[?] Warning: the file may be executed if this is not the CTX.Phage\n");
    printf("    infection.\n");
    printf("[?] Disinfect: (y)es / (n)o  ? \n");

    if (getch() == 'y') try_disinfect(name, where_ctx, caller, upa, sv);
    

  }

*)

//No for the easy part ;-)
//  error_mode4:
//    UnmapViewOfFile(mymap);
error_mode4:
  UnmapViewOfFile(mymap);

//  error_mode3:
//    CloseHandle(map);
error_mode3:
  CloseHandle(map);
    
//  error_mode2:
//    CloseHandle(file);
error_mode2:
  CloseHandle(file);

//  error_mode1:
//    DeleteFile(temp_name);
error_mode1:
  DeleteFile(temp_name);
//}
end;


mohfa - So 21.02.10 17:33

Sir BenBE , how could i translate this loop :


C#-Quelltext
1:
2:
3:
for (i = 0; (i != pSHC->SizeOfRawData); i++) 
  {
    loc = (DWORD)((DWORD)mymap + pSHC->PointerToRawData) + i;


Moderiert von user profile iconNarses: Code- durch C#-Tags ersetzt


BenBE - So 21.02.10 17:42

Try it this way:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
//for (i = 0; (i != pSHC->SizeOfRawData); i++) 
for i := 0 to pSHC^.SizeOfRawData - 1 do
//{
begin
//  loc = (DWORD)((DWORD)mymap + pSHC->PointerToRawData) + i;
  loc := DWORD(DWORD(mymap) + pSHC^.PointerToRawData) + i;


BTW: You should use [cs]-Tags for marking up C-Code (even though they are ment for C#, but that's quite simular).


mohfa - So 21.02.10 18:37

Thank you BenBE please take a look at It Now **** But i get an Exception *****

i use It like This :

Delphi-Quelltext
1:
scan_file('C:\myfile.exe',memo1.Lines);                    



Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
procedure scan_file(name: String;log:TStrings);
var
//  HANDLE file,map;
  cfile, map: THandle; //Actually this is HFile, but this doesn't really matter here
//  void* mymap;
  mymap: Pointer;
//  DWORD startrange = NULL, endrange = NULL, i = NULL, loc = NULL, temp_loc = NULL, upa = NULL;
  startrange, endrange, i, loc, temp_loc, upa: DWORD; //No inline initialization for local variables allowed in Delphi
//  DWORD where_ctx = NULL,caller = NULL, sv = NULL;
  where_ctx, caller, sv: DWORD; //Same goes here ...
//  PIMAGE_DOS_HEADER pMZ = NULL;
  pMZ: PIMAGE_DOS_HEADER;
//  PIMAGE_NT_HEADERS pPE = NULL;
  pPE: PIMAGE_NT_HEADERS;
//  PIMAGE_SECTION_HEADER pSH = NULL,pSHC = NULL;
  pSH, pSHC: PIMAGE_SECTION_HEADER;
//  char *temp_name = TEMP_FILE_NAME;
  temp_name: String;
//  WORD sections;
  sections: WORD;
//  int count=0;
  count: Integer;
  secname:pchar;
//label  //Usually those labels here should be translated as resource protection blocks with try-finally.
 // error_mode1, error_mode2, error_mode3, error_mode4;
begin
  startrange := 0;
  endrange := 0;
  i := 0;
  loc := 0;
  temp_loc := 0;
  upa := 0;
  where_ctx := 0;
  caller := 0;
  sv := 0;
  pMZ := nil;
  pPE := nil;
  pSH := nil;
  pSHC := nil;
  temp_name := TEMP_FILE_NAME;


  if not CopyFile(pchar(name),pchar(temp_name),FALSE) then

  begin
  log.Add(Format('[-] Error: copying file failed - no future disinfection possible, error: %d', [GetLastError()]));
  end;


  cfile := CreateFile(PChar(name), GENERIC_READ or FILE_SHARE_READ or FILE_SHARE_WRITE, 00, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  if cfile = INVALID_HANDLE_VALUE then

  begin

    log.Add(Format('[-] Error: Cannot open file - error: %d',[GetLastError()]));

   DeleteFile(temp_name);

  end;


  map := CreateFileMapping(cfile, nil, PAGE_READWRITE or SEC_COMMIT, 0,00);
  if map = 0 then

  begin

    log.Add(Format('[-] Error: Cannot create map of file - error: %d',[GetLastError()]));

  CloseHandle(cfile);

  end;


  mymap := MapViewOfFile(map,FILE_MAP_ALL_ACCESS,0,0,0);
  if mymap = nil then

  begin
    log.Add(format('"[-] Error: Cannot create map view of file - error: %d\n"',[GetLastError()]));

  CloseHandle(map);

  end;


  pMZ := PIMAGE_DOS_HEADER(mymap);


  if pMZ^.e_magic <> IMAGE_DOS_SIGNATURE then

  begin

    log.Add('[-] Error: Bad MZ signature');

  UnmapViewOfFile(mymap);

  end;


  pPE := PIMAGE_NT_HEADERS(DWORD(mymap) + pMZ^.e_lfanew);


  if IsBadReadPtr(pPE, sizeof(PIMAGE_NT_HEADERS)) then //DON'T EVER COMPARE BOOLEANS AGAINST CONSTANTS!

  begin

    log.Add('[-] Error: Bad PE file');

   UnmapViewOfFile(mymap);

  end;


  if (pPE^.Signature <> IMAGE_NT_SIGNATURE) or (pPE^.FileHeader.NumberOfSections = 0then

  begin

    log.Add('[-] Error: Bad PE file');

   UnmapViewOfFile(mymap);

  end;


  if (pPE^.OptionalHeader.ImageBase <= 0or (pPE^.OptionalHeader.AddressOfEntryPoint <= 0or (pPE^.FileHeader.NumberOfSections <= 0then

  begin
    log.Add('[-] Error: Bad PE file\n');

   UnmapViewOfFile(mymap);

  end;


  log.Add(Format('[+] Imagebase: 0x%.08x - Entrypoint: 0x%.08x (0x%.08x)\n', [pPE^.OptionalHeader.ImageBase, pPE^.OptionalHeader.AddressOfEntryPoint, pPE^.OptionalHeader.ImageBase + pPE^.OptionalHeader.AddressOfEntryPoint]));


  sections := pPE^.FileHeader.NumberOfSections;
  pSH := PIMAGE_SECTION_HEADER(DWORD(mymap)+pMZ^.e_lfanew + sizeof(IMAGE_NT_HEADERS));

while sections<>0
do
begin 
  if IsBadReadPtr(@pSH,sizeof(PIMAGE_SECTION_HEADER))=true
  then
  begin
    log.Add('[-] Error: Bad PE file'#13#10'');
    UnmapViewOfFile(mymap);
  end;
    secname:=(pSH^.Name);

    if (secname = nil)then strcopy(secname,'NONAME');

    startrange:=DWORD(pSH^.VirtualAddress+pPE^.OptionalHeader.ImageBase);

    endrange:=DWORD(startrange + pSH^.Misc.VirtualSize);
    if ((startrange<=0)or(startrange<=pPE^.OptionalHeader.ImageBase)or(endrange<=0)or(pPE^.OptionalHeader.ImageBase<=0)or(pSH^.Misc.PhysicalAddress<0)or(pSH^.SizeOfRawData<0 )) then

    begin
   log.Add(format('"[-] Error: The %s section is broken\n"',[secname]));

  UnmapViewOfFile(mymap);
  end;

  if ((pSH^.VirtualAddress<=pPE^.OptionalHeader.AddressOfEntryPoint)and(pPE^.OptionalHeader.AddressOfEntryPoint<pSH^.VirtualAddress+pSH^.Misc.VirtualSize))

  then
  begin
  log.Add(format('"[+] Checking call/jump requests from %s section (EP)\n"',[secname]));
      pSHC := pSH;
  end;

    begin
  inc(pSH);
  Dec(sections);
  
  end;

 Dec(pSH);
  if (pSHC = nil)

  then
   begin
  log.Add('Error: invalid entrypoint');
  UnmapViewOfFile(mymap);
  end;
  log.Add(format('"[+] Starting heuristics scan on %s section...\n\n"',[pSHC^.Name]));
  if (pSHC = pSH)

  then
 begin
 log.Add(format('"[!] Alert: Entrypoint points to last section (%s) -> 0x%.08x\n"',[pSH^.Name,pPE^.OptionalHeader.AddressOfEntryPoint + pPE^.OptionalHeader.ImageBase]));
 log.Add('[!] Alert: The file may be infected!');
 log.Add('[+] No deep-scan action was performed');

  UnmapViewOfFile(mymap);
 end;
 log.Add(format('"[+] Starting from offset: 0x%.08x\n"',[pPE^.OptionalHeader.ImageBase + pSHC^.VirtualAddress]));


for i := 0 to pSHC^.SizeOfRawData - 1 do

begin
  loc := DWORD(DWORD(mymap) + pSHC^.PointerToRawData) + i;
  if ((((BYTE(loc)) = O_CALL) or ((BYTE(loc)) = O_JMP )))

  then
  begin
    inc(loc);
    temp_loc:= (DWORD(((DWORD(pSHC^.VirtualAddress) + i + ((DWORD(loc))))))) + 5;

    if ((temp_loc>=pSH^.VirtualAddress)and(temp_loc<=pSH^.VirtualAddress+pSH^.Misc.VirtualSize))
    then
    begin
      log.Add(format('[!] Alert: Detected request to %s(0x%.08x) section at: 0x%.08x'#13#10'',[pSH^.Name,pPE^.OptionalHeader.ImageBase+temp_loc,pSHC^.VirtualAddress+pPE^.OptionalHeader.ImageBase+i]));
      if where_ctx=0{nil}
      then
      begin
        where_ctx:= {!!!a type cast? =>} {DWORD(}(pPE^.OptionalHeader.ImageBase+temp_loc);
        caller:= {!!!a type cast? =>} {DWORD(}(pSHC^.VirtualAddress+pPE^.OptionalHeader.ImageBase+i);
        upa:= {!!!a type cast? =>} {DWORD(}(pSH^.VirtualAddress+pPE^.OptionalHeader.ImageBase);
        sv:= loc-1
      end;
      inc(count);
    end;
    dec(loc); 
  end;
end;

log.Add(format('"[+] Scan finished, %d suspected instruction(s) found.\n"',[count]));
  if (count = 0)
  then
  begin
    log.Add('"[!] Warning: the file may be infected!\n"');
    log.Add('"\n[?] Do you want to try dis-infect the file?\n"');
    log.Add('"[?] Warning: the file may be executed if this is not the CTX.Phage\n"');
    log.Add('"    infection.\n"');
    log.Add('"[?] Disinfect: (y)es / (n)o  ? \n"');

  //  if (getch() == 'y') try_disinfect(name, where_ctx, caller, upa, sv);
    
  end;

end;
end;


jaenicke - So 21.02.10 18:39

And where do you get the exception? When you debug this piece of code line by line you can see this.

Which exception do you get?


mohfa - So 21.02.10 18:44

here :

Delphi-Quelltext
1:
log.Add(format('"[+] Starting heuristics scan on %s section.."',[pSHC^.Name]));                    


BenBE - So 21.02.10 18:53

Can you have a look at the value of pSHC? Should be <> nil.

But I see another, major problem in your source. The Gotos in the Source as I wrote it had their reason and should stay there. If you wanted to remove them you'd have to use try-finally blocks.

This issue manifests e.g. if you get an error in the setup phase, delete your file, but instead of exiting the procedure continue and try to create a file mapping of a closed (and deleted) file.


mohfa - So 21.02.10 19:16

Thank you all especially BenBE .

Now it works , I reset the use of GoTos.


BenBE - So 21.02.10 19:24

Maybe you post your final solution so I can show you the way without Gotos. It's actually not that hard to do.


mohfa - So 21.02.10 19:50

Ok Sir BenBE here it's :


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
procedure scan_file(name: String;log:TStrings);
var
//  HANDLE file,map;
  cfile, map: THandle; //Actually this is HFile, but this doesn't really matter here
//  void* mymap;
  mymap: Pointer;
//  DWORD startrange = NULL, endrange = NULL, i = NULL, loc = NULL, temp_loc = NULL, upa = NULL;
  startrange, endrange, i, loc, temp_loc, upa: DWORD; //No inline initialization for local variables allowed in Delphi
//  DWORD where_ctx = NULL,caller = NULL, sv = NULL;
  where_ctx, caller, sv: DWORD; //Same goes here ...
//  PIMAGE_DOS_HEADER pMZ = NULL;
  pMZ: PIMAGE_DOS_HEADER;
//  PIMAGE_NT_HEADERS pPE = NULL;
  pPE: PIMAGE_NT_HEADERS;
//  PIMAGE_SECTION_HEADER pSH = NULL,pSHC = NULL;
  pSH, pSHC: PIMAGE_SECTION_HEADER;
//  char *temp_name = TEMP_FILE_NAME;
  temp_name: String;
//  WORD sections;
  sections: WORD;
//  int count=0;
  count: Integer;
  secname:pchar;
label  //Usually those labels here should be translated as resource protection blocks with try-finally.
  error_mode1, error_mode2, error_mode3, error_mode4;
begin
  startrange := 0;
  endrange := 0;
  i := 0;
  loc := 0;
  temp_loc := 0;
  upa := 0;
  where_ctx := 0;
  caller := 0;
  sv := 0;
  pMZ := nil;
  pPE := nil;
  pSH := nil;
  pSHC := nil;
  temp_name := TEMP_FILE_NAME;


  if not CopyFile(pchar(name),pchar(temp_name),FALSE) then

  begin
  log.Add(Format('[-] Error: copying file failed - no future disinfection possible, error: %d', [GetLastError()]));
  end;


  cfile := CreateFile(PChar(name), GENERIC_READ or FILE_SHARE_READ or FILE_SHARE_WRITE, 00, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  if cfile = INVALID_HANDLE_VALUE then

  begin

    log.Add(Format('[-] Error: Cannot open file - error: %d',[GetLastError()]));

 //  DeleteFile(temp_name);
   goto error_mode1;
  end;


  map := CreateFileMapping(cfile, nil, PAGE_READWRITE or SEC_COMMIT, 0,00);
  if map = 0 then

  begin

    log.Add(Format('[-] Error: Cannot create map of file - error: %d',[GetLastError()]));

//  CloseHandle(cfile);
   goto error_mode2;
  end;


  mymap := MapViewOfFile(map,FILE_MAP_ALL_ACCESS,0,0,0);
  if mymap = nil then

  begin
    log.Add(format('"[-] Error: Cannot create map view of file - error: %d\n"',[GetLastError()]));

 // CloseHandle(map);
  goto error_mode3;
  end;


  pMZ := PIMAGE_DOS_HEADER(mymap);


  if pMZ^.e_magic <> IMAGE_DOS_SIGNATURE then

  begin

    log.Add('[-] Error: Bad MZ signature');

 // UnmapViewOfFile(mymap);
  goto error_mode4;
  end;


  pPE := PIMAGE_NT_HEADERS(DWORD(mymap) + pMZ^.e_lfanew);


  if IsBadReadPtr(pPE, sizeof(PIMAGE_NT_HEADERS)) then //DON'T EVER COMPARE BOOLEANS AGAINST CONSTANTS!

  begin

    log.Add('[-] Error: Bad PE file');

 //  UnmapViewOfFile(mymap);
   goto error_mode4;
  end;


  if (pPE^.Signature <> IMAGE_NT_SIGNATURE) or (pPE^.FileHeader.NumberOfSections = 0then

  begin

    log.Add('[-] Error: Bad PE file');

 //  UnmapViewOfFile(mymap);
   goto error_mode4;
  end;


  if (pPE^.OptionalHeader.ImageBase <= 0or (pPE^.OptionalHeader.AddressOfEntryPoint <= 0or (pPE^.FileHeader.NumberOfSections <= 0then

  begin
    log.Add('[-] Error: Bad PE file\n');

 //  UnmapViewOfFile(mymap);
  goto error_mode4;
  end;


  log.Add(Format('[+] Imagebase: 0x%.08x - Entrypoint: 0x%.08x (0x%.08x)\n', [pPE^.OptionalHeader.ImageBase, pPE^.OptionalHeader.AddressOfEntryPoint, pPE^.OptionalHeader.ImageBase + pPE^.OptionalHeader.AddressOfEntryPoint]));


  sections := pPE^.FileHeader.NumberOfSections;
  pSH := PIMAGE_SECTION_HEADER(DWORD(mymap)+pMZ^.e_lfanew + sizeof(IMAGE_NT_HEADERS));

while sections<>0
do
begin 
  if IsBadReadPtr(@pSH,sizeof(PIMAGE_SECTION_HEADER))=true
  then
  begin
    log.Add('[-] Error: Bad PE file'#13#10'');
    UnmapViewOfFile(mymap);
  end;
    secname:=(pSH^.Name);

    if (secname = nil)then strcopy(secname,'NONAME');

    startrange:=DWORD(pSH^.VirtualAddress+pPE^.OptionalHeader.ImageBase);

    endrange:=DWORD(startrange + pSH^.Misc.VirtualSize);
    if ((startrange<=0)or(startrange<=pPE^.OptionalHeader.ImageBase)or(endrange<=0)or(pPE^.OptionalHeader.ImageBase<=0)or(pSH^.Misc.PhysicalAddress<0)or(pSH^.SizeOfRawData<0 )) then

    begin
   log.Add(format('"[-] Error: The %s section is broken\n"',[secname]));

//  UnmapViewOfFile(mymap);
   goto error_mode4;
  end;

  if ((pSH^.VirtualAddress<=pPE^.OptionalHeader.AddressOfEntryPoint)and(pPE^.OptionalHeader.AddressOfEntryPoint<pSH^.VirtualAddress+pSH^.Misc.VirtualSize))

  then
  begin
  log.Add(format('"[+] Checking call/jump requests from %s section (EP)\n"',[secname]));
      pSHC := pSH;
  end;

    begin
  inc(pSH);
  Dec(sections);
  
  end;

 Dec(pSH);
  if (pSHC = nil)

  then
   begin
  log.Add('Error: invalid entrypoint');
  exit;
 // UnmapViewOfFile(mymap);
 goto error_mode4;
  end;
  log.Add(format('"[+] Starting heuristics scan on %s section.."',[pSHC^.Name]));
  if (pSHC = pSH)

  then
 begin
 log.Add(format('"[!] Alert: file %s Entrypoint points to last section (%s) -> 0x%.08x\n"',[name,pSH^.Name,pPE^.OptionalHeader.AddressOfEntryPoint + pPE^.OptionalHeader.ImageBase]));
 log.Add(format('[!] Alert: The file %s may be infected!',[name]));
 log.Add('[+] No deep-scan action was performed');

 // UnmapViewOfFile(mymap);
 goto error_mode4;
 end;
 log.Add(format('"[+] Starting from offset: 0x%.08x\n"',[pPE^.OptionalHeader.ImageBase + pSHC^.VirtualAddress]));


for i := 0 to pSHC^.SizeOfRawData - 1 do

begin
  loc := DWORD(DWORD(mymap) + pSHC^.PointerToRawData) + i;
  if ((((BYTE(loc)) = O_CALL) or ((BYTE(loc)) = O_JMP )))

  then
  begin
    inc(loc);
    temp_loc:= (DWORD(((DWORD(pSHC^.VirtualAddress) + i + ((DWORD(loc))))))) + 5;

    if ((temp_loc>=pSH^.VirtualAddress)and(temp_loc<=pSH^.VirtualAddress+pSH^.Misc.VirtualSize))
    then
    begin
      log.Add(format('-------->[!] Alert: file %s Detected request to %s(0x%.08x) section at: 0x%.08x'#13#10'',[name,pSH^.Name,pPE^.OptionalHeader.ImageBase+temp_loc,pSHC^.VirtualAddress+pPE^.OptionalHeader.ImageBase+i]));
      if where_ctx=0{nil}
      then
      begin
        where_ctx:= {!!!a type cast? =>} {DWORD(}(pPE^.OptionalHeader.ImageBase+temp_loc);
        caller:= {!!!a type cast? =>} {DWORD(}(pSHC^.VirtualAddress+pPE^.OptionalHeader.ImageBase+i);
        upa:= {!!!a type cast? =>} {DWORD(}(pSH^.VirtualAddress+pPE^.OptionalHeader.ImageBase);
        sv:= loc-1
      end;
      inc(count);
    end;
    dec(loc);
  end;
end;

log.Add(format('"[+] Scan finished, %d suspected instruction(s) found.\n"',[count]));
  if (count = 0)
  then
  begin
    log.Add(Format('"--------->[!] Warning: the file may be infected!\n %s"',[name]));
    log.Add('"\n[?] Do you want to try dis-infect the file?\n"');
    log.Add(Format('"---------> [?] Warning: the file may be executed if this is not the CTX.Phage\n %s "',[name]));
    log.Add('"    infection.\n"');
    log.Add('"[?] Disinfect: (y)es / (n)o  ? \n"');

  //  if (getch() == 'y') try_disinfect(name, where_ctx, caller, upa, sv);

  end;

end;
error_mode4:
UnmapViewOfFile(mymap);
error_mode3:
CloseHandle(map);
error_mode2: 
CloseHandle(cfile);
error_mode1:
DeleteFile(temp_name);
end;


BenBE - So 21.02.10 20:31

Okay, when I didn't screw something up when changing the resource allocations this should do the trick:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
Procedure scan_file(name: String; log: TStrings);
Var
    //  HANDLE file,map;
    cfile, map: THandle; //Actually this is HFile, but this doesn't really matter here
    //  void* mymap;
    mymap: Pointer;
    //  DWORD startrange = NULL, endrange = NULL, i = NULL, loc = NULL, temp_loc = NULL, upa = NULL;
    startrange, endrange, i, loc, temp_loc, upa: DWORD; //No inline initialization for local variables allowed in Delphi
    //  DWORD where_ctx = NULL,caller = NULL, sv = NULL;
    where_ctx, caller, sv: DWORD; //Same goes here ...
    //  PIMAGE_DOS_HEADER pMZ = NULL;
    pMZ: PIMAGE_DOS_HEADER;
    //  PIMAGE_NT_HEADERS pPE = NULL;
    pPE: PIMAGE_NT_HEADERS;
    //  PIMAGE_SECTION_HEADER pSH = NULL,pSHC = NULL;
    pSH, pSHC: PIMAGE_SECTION_HEADER;
    //  char *temp_name = TEMP_FILE_NAME;
    temp_name: String;
    //  WORD sections;
    sections: WORD;
    //  int count=0;
    count: Integer;
    secname: PChar;
Begin
    startrange := 0;
    endrange := 0;
    i := 0;
    loc := 0;
    temp_loc := 0;
    upa := 0;
    where_ctx := 0;
    caller := 0;
    sv := 0;
    pMZ := Nil;
    pPE := Nil;
    pSH := Nil;
    pSHC := Nil;
    temp_name := TEMP_FILE_NAME;

    If Not CopyFile(pchar(name), pchar(temp_name), FALSE) Then
    Begin
        log.Add(Format('[-] Error: copying file failed - no future disinfection possible, error: %d', [GetLastError()]));
    End;

    Try

        cfile := CreateFile(PChar(name), GENERIC_READ Or FILE_SHARE_READ Or FILE_SHARE_WRITE, 00, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
        If cfile = INVALID_HANDLE_VALUE Then
        Begin
            log.Add(Format('[-] Error: Cannot open file - error: %d', [GetLastError()]));
            exit;
        End;

        Try

            map := CreateFileMapping(cfile, Nil, PAGE_READWRITE Or SEC_COMMIT, 000);
            If map = 0 Then
            Begin
                log.Add(Format('[-] Error: Cannot create map of file - error: %d', [GetLastError()]));
                exit;
            End;

            Try

                mymap := MapViewOfFile(map, FILE_MAP_ALL_ACCESS, 000);
                If mymap = Nil Then
                Begin
                    log.Add(format('"[-] Error: Cannot create map view of file - error: %d\n"', [GetLastError()]));
                    exit;
                End;

                Try

                    pMZ := PIMAGE_DOS_HEADER(mymap);
                    If pMZ^.e_magic <> IMAGE_DOS_SIGNATURE Then
                    Begin
                        log.Add('[-] Error: Bad MZ signature');
                        exit;
                    End;

                    pPE := PIMAGE_NT_HEADERS(DWORD(mymap) + pMZ^.e_lfanew);
                    If IsBadReadPtr(pPE, sizeof(PIMAGE_NT_HEADERS)) Then //DON'T EVER COMPARE BOOLEANS AGAINST CONSTANTS!
                    Begin
                        log.Add('[-] Error: Bad PE file');
                        exit;
                    End;

                    If (pPE^.Signature <> IMAGE_NT_SIGNATURE) Or (pPE^.FileHeader.NumberOfSections = 0Then
                    Begin
                        log.Add('[-] Error: Bad PE file');
                        exit;
                    End;

                    If (pPE^.OptionalHeader.ImageBase <= 0Or (pPE^.OptionalHeader.AddressOfEntryPoint <= 0Or (pPE^.FileHeader.NumberOfSections <= 0Then
                    Begin
                        log.Add('[-] Error: Bad PE file\n');
                        exit;
                    End;

                    log.Add(Format('[+] Imagebase: 0x%.08x - Entrypoint: 0x%.08x (0x%.08x)\n', [pPE^.OptionalHeader.ImageBase, pPE^.OptionalHeader.AddressOfEntryPoint, pPE^.OptionalHeader.ImageBase + pPE^.OptionalHeader.AddressOfEntryPoint]));

                    sections := pPE^.FileHeader.NumberOfSections;
                    pSH := PIMAGE_SECTION_HEADER(DWORD(mymap) + pMZ^.e_lfanew + sizeof(IMAGE_NT_HEADERS));

                    While sections <> 0 Do
                    Begin
                        If IsBadReadPtr(@pSH, sizeof(PIMAGE_SECTION_HEADER)) = true Then
                        Begin
                            log.Add('[-] Error: Bad PE file'#13#10'');
                            UnmapViewOfFile(mymap);
                        End;

                        secname := pSH^.Name;

                        If secname = Nil Then
                            strcopy(secname, 'NONAME');

                        startrange := DWORD(pSH^.VirtualAddress + pPE^.OptionalHeader.ImageBase);

                        endrange := DWORD(startrange + pSH^.Misc.VirtualSize);
                        If (startrange <= 0Or (startrange <= pPE^.OptionalHeader.ImageBase) Or (endrange <= 0Or (pPE^.OptionalHeader.ImageBase <= 0Or (pSH^.Misc.PhysicalAddress < 0Or (pSH^.SizeOfRawData < 0Then
                        Begin
                            log.Add(format('"[-] Error: The %s section is broken\n"', [secname]));
                            Exit;
                        End;

                        If ((pSH^.VirtualAddress <= pPE^.OptionalHeader.AddressOfEntryPoint) And (pPE^.OptionalHeader.AddressOfEntryPoint < pSH^.VirtualAddress + pSH^.Misc.VirtualSize)) Then
                        Begin
                            log.Add(format('"[+] Checking call/jump requests from %s section (EP)\n"', [secname]));
                            pSHC := pSH;
                        End;

                        //Usually no blocks without need for them should be used.name I.e. those statements can go without begin\end
                        //Is this really correct?
                        Begin
                            inc(pSH);
                            Dec(sections);
                        End;

                        Dec(pSH);
                        If (pSHC = NilThen
                        Begin
                            log.Add('Error: invalid entrypoint');
                            exit;
                        End;

                        log.Add(format('"[+] Starting heuristics scan on %s section.."', [pSHC^.Name]));
                        If (pSHC = pSH) Then
                        Begin
                            log.Add(format('"[!] Alert: file %s Entrypoint points to last section (%s) -> 0x%.08x\n"', [name, pSH^.Name, pPE^.OptionalHeader.AddressOfEntryPoint + pPE^.OptionalHeader.ImageBase]));
                            log.Add(format('[!] Alert: The file %s may be infected!', [name]));
                            log.Add('[+] No deep-scan action was performed');

                            Exit;
                        End;
                        log.Add(format('"[+] Starting from offset: 0x%.08x\n"', [pPE^.OptionalHeader.ImageBase + pSHC^.VirtualAddress]));

                        For i := 0 To pSHC^.SizeOfRawData - 1 Do
                        Begin
                            loc := DWORD(DWORD(mymap) + pSHC^.PointerToRawData) + i;
                            If ((((BYTE(loc)) = O_CALL) Or ((BYTE(loc)) = O_JMP))) Then
                            Begin
                                inc(loc);
                                temp_loc := (DWORD(((DWORD(pSHC^.VirtualAddress) + i + ((DWORD(loc))))))) + 5;

                                If ((temp_loc >= pSH^.VirtualAddress) And (temp_loc <= pSH^.VirtualAddress + pSH^.Misc.VirtualSize)) Then
                                Begin
                                    log.Add(format('-------->[!] Alert: file %s Detected request to %s(0x%.08x) section at: 0x%.08x'#13#10'', [name, pSH^.Name, pPE^.OptionalHeader.ImageBase + temp_loc, pSHC^.VirtualAddress + pPE^.OptionalHeader.ImageBase + i]));
                                    If where_ctx = 0 {nil} Then
                                    Begin
                                        where_ctx := {!!!a type cast? =>} {DWORD(}(pPE^.OptionalHeader.ImageBase + temp_loc);
                                        caller := {!!!a type cast? =>} {DWORD(}(pSHC^.VirtualAddress + pPE^.OptionalHeader.ImageBase + i);
                                        upa := {!!!a type cast? =>} {DWORD(}(pSH^.VirtualAddress + pPE^.OptionalHeader.ImageBase);
                                        sv := loc - 1;
                                    End;
                                    inc(count);
                                End;
                                dec(loc);
                            End;
                        End;

                        log.Add(format('"[+] Scan finished, %d suspected instruction(s) found.\n"', [count]));
                        If (count = 0Then
                        Begin
                            log.Add(Format('"--------->[!] Warning: the file may be infected!\n %s"', [name]));
                            log.Add('"\n[?] Do you want to try dis-infect the file?\n"');
                            log.Add(Format('"---------> [?] Warning: the file may be executed if this is not the CTX.Phage\n %s "', [name]));
                            log.Add('"    infection.\n"');
                            log.Add('"[?] Disinfect: (y)es / (n)o  ? \n"');

                            //  if (getch() == 'y') try_disinfect(name, where_ctx, caller, upa, sv);

                        End;

                    End;

                Finally
                    //error_mode4:
                    UnmapViewOfFile(mymap);
                End;

            Finally
                //error_mode3:
                CloseHandle(map);
            End;

        Finally
            //error_mode2:
            CloseHandle(cfile);
        End;

    Finally
        //error_mode1:
        DeleteFile(temp_name);
    End;

End;


Please note the one single statement block I added a comment ... There seems to be something missing OR the block statements around those instructions should be removed.