Showing posts with label IDA. Show all posts
Showing posts with label IDA. Show all posts

Thursday, February 16, 2023

Redline Malware Malware Analysis Feb 16 2023

Started with this redline malware sample 

https://www.joesandbox.com/analysis/808971/0/html

Which the sandbox says dumps a bunch of child-processes and eventually drops these 2 payloads

AV killer

https://www.virustotal.com/gui/file/850cd190aaeebcf1505674d97f51756f325e650320eaf76785d954223a9bee38

Healer.exe

MD5 7e93bacbbc33e6652e147e7fe07572a0

SHA-1 421a7167da01c8da4dc4d5234ca3dd84e319e762



Infostealer

https://www.virustotal.com/gui/file/dc28c9d9ab3f30222ed59f3991c5981bec40604e725ece488d8599eef917a7b3 

The Infostealer looks a lot like this blog ( https://securityscorecard.com/research/detailed-analysis-redline-stealer/ )

Franchise.exe

MD5 dd0c9e110c68ce1fa5308979ef718f7b

SHA-1 473deb8069f0841d47b74b7f414dacc6f96eca78


C2: 193.233.20.13:4136


It is stored in a self extracting .CAB file (microsoft cabinet)

It unpacks itself 4 times actually before we finally see the payload.

Each time the child .CAB file is stored in a Resource named "CABINET"

Each time there is 2 .exes inside the .CAB .

Each of the repeated dumps the "RUNPROGRAM" resource launches another child .CAB extractor.







Eventually though on the last extract it's 2 .NET executables instead of X86 and .CAB extrator.



The first .NET executable is an AV killer that turns off defender, windows updates, etc.



The 2nd .nET executable is the infostealer that grabs wallets, vpn , discord, and much more








                                            
There are some Russian characters and nearby region country names



There is also code for the c2 command and control traffic that is Xor'd with a key "Sigma" and base64 encoded. 193.233.20.13:4136











CAB files FDICreate FDICopy

 call ds:__imp__FDICreate (creates context for extracting Microsoft .CAB Cabinet files)

...

push offset pszCabPath 

call ds:__imp__FDICopy


You should see memory for the Cabinet (or CAB archive-file format) recognized by their first four bytes (also called their magic number) MSCF

After the FDICopy you'll see extracted files (possibly .exe malware) in the file path that was in pszCabPath

FindResourceA 0xa

 v0 = FindResourceA(0, "UPROMPT", (LPCSTR)0xA);


or


push 0xA ; lpType

push edi ; lpName

push 0 ; hModule

call ds:__imp__FindresourceA@12


This is grabbing a handle to a resource string from RCData with the name "UPROMPT" (you can see this in resource hacker)  ... please note it'll follow by using "LoadResourceA" to actually get the string value and put it into EAX

0xA = 10 = RT_RCDATA = Application-defined resource (raw data)

0 for hModule = use this current executable's resources

pointer to the resulting string is put into eax


Wednesday, February 15, 2023

Packer Process Injection - CreateProcessInternalW CREATE_SUSPENDED

CreateProcessInternalW

CreationFlags: CREATE_SUSPENDED 0x00000004


Malware creating a process in a suspended state


typically from a packer and process injection

it has unpacked code and is injecting it into a user process


will be followed with calls like 


NtGetContextThread

ReadProcessMemory

memcpy

WriteProcessMemory ('MZ')

NetSetContextThread

NtResumeThread


to edit memory of suspended process and inject the malicious code

VirtualProtectEx PAGE_EXECUTE_READWRITE

 VirtualProtectEx

Protection: PAGE_EXECUTE_READWRITE 0x40


in malware that almost always means "injected code"


Tuesday, February 14, 2023

IDA Pro - The graph is too big (more than 1000 nodes)

 IDA Pro error

The graph is too big (more than 1000 nodes)


two options as to why the graph is "too big"

1) either it's obfuscated somehow

2) or it's packed



Wednesday, October 19, 2022

IDA Pro Reversing notes

 Notes just for me learning


CPPEH_RECORD = exception handling

__guard_check_icall_fptr = control flow guard

_initterm = creation function pointer table


Thursday, September 30, 2021

IDA Pro Keyboard Shortcuts

 Ascii strings

"highlight the string", press 'a'


Unicode strings

highlight the ascii string, press 'Alt-a', choose unicode


Rename variable

highlight variable, press 'n'


Cross References

highlight the variable, press 'x'


Step

into f7

over f8

run until return ctrl-f7

continue f9


Breakpoint

f2


jump to address

press 'g', enter address


Strings

Shift-f12


comment a line

press ';', enter the comment

Friday, April 16, 2021

Generic unpacking malware steps

1.) Open malware in IDA

2.) Find the 'ret' of WinMain and look for closes "call" statements above it

3.) Find a VirtualAlloc, follow the EAX result get passed around until you see it in a "call" statement

4.) Find the address of that "call" statement

5.) Flip over to x32dbg, open the same malware, put a breakpoint on the address of the "call"

6.) Also set a breakpoint on VirtualAlloc (bp VirtualAlloc)

7.) Run until breakpoints, Follow in Dump repeatedly on EAX, looking at previous dumps

8.) Find MZ header that does not match original (use Hex Editor to compare)

9.) Follow in memory map, Dump to File, review in PE Studio to see if unpacked

 

FlawedAmmyy unpacking malware example

 FlawedAmmyy unpacking

https://guidedhacking.com/threads/how-to-unpack-flawedammyy-malware-unpacking-tutorial.16637/

7fb83e646cbabc50bec4b33c8130b5ae

https://app.any.run/tasks/97d8c688-a0ed-4602-af79-2409b6d8cd47/


steps

- open ida

- find bottom of "start" (using graph overview window)

- notice all to "WinMain", take it

- find "ret" near bottom of "WinMain" (using graph overview window)

- look just above & around to find any "call" statements, choose "call" closest to the "ret"

- find return of VirtualAlloc

- follow as it's moved from EAX to a "var_**"

- then moved to a register

- then moved to another "var_**"

- until you find a "call var_**" to near the end of the chain

- switch from graph to text view, find the memory address of the "call" statement (0x0040153F)

- open x32dbg

- right-click in CPU tab, "Go To -> Expression", enter that address "0x0040153F"

- cursor should be at same "call" statement as we had in IDA

- set a breakoint in x32dbg on that "call" statement (F2)

- push the play arrow (twice) and run to the breakpoint

- right-click on the "call" statement, choose "Follow in Dump -> Value" (no MX value yet)

- step into the "call" (F7)

- notice code has lots of Stack Strings (API calls like VirtualAlloc, VirtualProtect, etc.)

- when you see "VirtualAlloc", good time to put a breakpoint on all future calls (command: bp VirtualAlloc)

- scroll down until you find either a "call REGISTER", "jmp REGISTER", or "call/jmp DWORD that was a register"

ex: mov dword ptr ss:[ebp-54],eax

call word ptr ss:[ebp-54]

- set a breakpoint (F2) on the registry call

- then run by hitting play arrow

- If "VirtualAlloc" breakpoint is hit, right-click on EAX and "Follow in Dump"

- Keep going until the "Follow in Dump" shows a value at the bottom starting with "MZ" header

- open Hex Editor

- compare original EXE first chars after "MZ" header with what is in "Follow in Dump"

- if same, then hit play arrow again to keep running

- if different, then you may have the unpacked EXE

notes: It may take a while (unpacking can be slow)

When you hit a breakpoint you're looking at the content of "previous" memory regions

- right click "Follow in Memory Map"

- right click "Dump Memory to File"

- how do you know if you did it right?

drop into PE Studio, look at strings, do you see the actual "Ammyy.Service" or "ammy\svn" strings? 

Wednesday, December 30, 2020

IDA Pro Xref Notes

 https://resources.infosecinstitute.com/topic/ida-cross-references-xrefs/

XREF , "...After the arrow, there’s also a single letter..."

- letter ‘j’ denotes the jump

- letter ‘p’ denotes the function call


DATA XREF, "...letters assigned after the arrow ..." 

- letter ‘w’ denotes that the location is being written to

- letter ‘r’ denotes that the location is being read from

- letter ‘o’ denotes that the address of the location is being taken from it


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

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  ***                ***

Thursday, July 16, 2020

IDA Pro Debug Load DLL export function, getting Error WerMgr fault

If you are trying to debug a DLL and getting a wermgr fault using IDA it may be because you are using the WRONG version of rundll32.exe

there are 2 versions on a 64 bit windows 7/10 machine

c:\windows\system32\rundll32.exe    <-- this is the 64 bit and should be used with 64 bit dlls
c:\windows\syswow64\rundll32.exe  <-- this is the 32 bit and should be used with 32 bit dlls

so if i am analyzing a DLL with an export function such as "update.dll" with function "StartW"

if i open in PEstudio and see that it's a 32 bit DLL then my IDA Debugger -> process options would be

Application: c:\windows\syswow64\rundll32.exe
Input file: [my dll path]
Directory: [my dll folder]
Parameters: [my dll path], [my export function]

I noticed that initially i was trying
Application: c:\windows\system32\rundll32.exe

but rundll32 would just crash and IDA would never hit my breakpoint
but if i changed it to
Application: c:\windows\syswow64\rundll32.exe

then it would hit my breakpoint in IDA

nice!