
/**
 * @file: main.c
 *
 * Hlavni soubor programu ListDll, ktery dovoluje zjistit seznam modulu
 * ciloveho procesu nekolika ruznymi metodami. Lze tak potencialne
 * odhalit skryte knihovny DLL.
 *
 * Syntaxe: ListDll <metoda> <PID>
 * <metoda>                    Identifikace metody, kterou ma program pouzit
 * <PID>                       Identifikator ciloveho procesu
 *
 * Podporovane metody:
 * --toolhelp                  Knihovna Toolhelp
 * --peb                       Prochazeni struktur bloku prostredi procesu
 * --vm                        Vyuziti sluzeb spravce virtualni pameti
 */

#include <stdio.h>
#include <windows.h>
#include "common.h"
#include "moduleinfo.h"
#include "listdll-vm.h"
#include "listdll-toolhelp.h"
#include "listdll-peb.h"


/** Zajisti inicializaci vsech soucasti programu.
 *
 *  @return Funkce vrati TRUE v pripade uspechu a FALSE v pripade 
 *  neuspechu.
 */
BOOL ModulesInit(VOID)
{
  BOOL Ret = FALSE;

  Ret = CommonInit();
  if (Ret) {
    if (!EnablePrivilege(L"SeDebugPrivilege"))
      printf("Nepidarilo se povolit opravneni SeDebugPrivilege. Schopnosti programu budou omezeny\n");

    Ret = ModuleInfoInit();
	if (Ret) {
      Ret = ListDllVMInit();
      if (Ret) {
        Ret = ListDllToolHelpInit();
        if (Ret) {
          Ret = ListDllPEBInit();
          if (!Ret) {
            ListDllToolHelpFinit();
            ListDllVMFinit();
            ModuleInfoFinit();
            CommonFinit();
		  }
        } else {
          ListDllVMFinit();
          ModuleInfoFinit();
          CommonFinit();
		}
	  } else {
        ModuleInfoFinit();
        CommonFinit();
	  }
	} else CommonFinit();
  }

  return Ret;
}


/** Zajisti provedeni uklidu po vsech soucastech programu.
 */
VOID ModulesFinit(VOID)
{
  ListDllPEBFinit();
  ListDllToolHelpFinit();
  ListDllVMFinit();
  ModuleInfoFinit();
  CommonFinit();

  return;
}


/** Vytiskne seznam modulu reprezentovany strukturami MODULE_INFO_ITEM
 *  na standardni vystup.
 *
 *  @param ListStart Adresa struktury MODULE_INFO_ITEM reprezentujici
 *  prvni prvek seznamu.
 */
VOID PrintModuleList(PMODULE_INFO_ITEM ListStart)
{
  while (ListStart != NULL) {
    printf("0x%p\t%u bajtu\t\t%S\n", ListStart->BaseAddress, ListStart->Size, ListStart->Name);
    ListStart = ListStart->Next;
  }

  return;
}


/** Hlavni funkce programu. Na zaklade argumentu prikazove radky rozhodne,
 *  kterou metodu ziskani seznamu modulu z ciloveho procesu pouzit, a
 *  a zajisti vypis jejich vysledku na standardni vystup.
 *
 *  @param argc Pocet argumentu prikazove radky (vcetne jmena souboru).
 *  @param argv obsah argumentu prikazove radky.
 *
 *  @return Funkce vraci vzdy nulu.
 */
int main(int argc, char **argv)
{
  DWORD PID = 0;
  BOOL Ret = FALSE;
  PMODULE_INFO_ITEM ModuleList = NULL;

  Ret = ModulesInit();
  if (Ret) {
    if (argc == 3) {
      Ret = FALSE;
      PID = strtoul(argv[2], NULL, 0);
      if (strncmp(argv[1], "--vm", strlen("--vm")) == 0) {
        Ret = ListDllVMGetModules(PID, &ModuleList);
        if (!Ret)
          printf("Pri zjistovani seznamu modulu doslo k chybe\n");
      } else if (strncmp(argv[1], "--toolhelp", strlen("--toolhelp")) == 0) {
        Ret = ListDllToolHelpGetModules(PID, &ModuleList);
        if (!Ret)
          printf("Pri zjistovani seznamu modulu doslo k chybe\n");
      } else if (strncmp(argv[1], "--peb", strlen("--peb")) == 0) {
        Ret = ListDllPEBGetModules(PID, &ModuleList);
        if (!Ret)
          printf("Pri zjistovani seznamu modulu doslo k chybe\n");      
      } else printf("Neznama metoda zjistovani seznamu modulu\n");

      if (Ret) {
        PrintModuleList(ModuleList);
        ModuleInfoListFree(ModuleList);
      }
    } else printf("Syntaxe: listdll <metoda> <PID>\n");

    ModulesFinit();
  } else printf("Pri inicializaci doslo k chybe\n");

  return 0;
}
