Printing values from linear addresses with IDAPython

While working on a CTF challenge recently, I needed a way to print all the values in a range of linear addresses to avoid some manual labor. I’m pretty new to IDA Pro but a friend told me about the function GetManyBytes which turned out to be extremely useful. By the way, Hex-Ray has pretty good documentation here.

Taking the following values as example:

.data:00403000 byte_403000 db 0Dh ; DATA XREF: sub_401050+84r
.data:00403001 db 26h ; &
.data:00403002 db 49h ; I
.data:00403003 db 45h ; E
.data:00403004 db 2Ah ; *
.data:00403005 db 17h
.data:00403006 db 78h ; x
.data:00403007 db 44h ; D
.data:00403008 db 2Bh ; +
.data:00403009 db 6Ch ; l
.data:0040300A db 5Dh ; ]
.data:0040300B db 5Eh ; ^
.data:0040300C db 45h ; E
.data:0040300D db 12h
.data:0040300E db 2Fh ; /
.data:0040300F db 17h
.data:00403010 db 2Bh ; +
.data:00403011 db 44h ; D
.data:00403012 db 6Fh ; o
.data:00403013 db 6Eh ; n
.data:00403014 db 56h ; V
.data:00403015 db 9
.data:00403016 db 5Fh ; _
.data:00403017 db 45h ; E
.data:00403018 db 47h ; G
.data:00403019 db 73h ; s
.data:0040301A db 26h ; &
.data:0040301B db 0Ah
.data:0040301C db 0Dh
.data:0040301D db 13h
.data:0040301E db 17h
.data:0040301F db 48h ; H
.data:00403020 db 42h ; B
.data:00403021 db 1
.data:00403022 db 40h ; @
.data:00403023 db 4Dh ; M
.data:00403024 db 0Ch
.data:00403025 db 2
.data:00403026 db 69h ; i
.data:00403027 db 0

We can loop through each address and return the values we want by specifying the start address and the size of the buffer:

for b in GetManyBytes(0x00403000, 0x27):
 print "%X" % ord(b)

Result:

Python>for b in GetManyBytes(0x00403001, 27): print "%X" % ord(b)
D
26
49
45
2A
17
78
44
2B
6C
5D
5E
45
12
2F
17
2B
44
6F
6E
56
9
5F
45
47
73
26
A
D
13
17
48
42
1
40
4D
C
2
69
D
26
49
45
2A
17
78
44
2B
6C
5D
5E
45
12
2F
17
2B
44
6F
6E
56
9
5F
45
47
73
26
A
D
13
17
48
42
1
40
4D
C
2
69
Advertisements

Leveraging Splunk Enterprise Security threat intelligence features to increase detection capabilities.

Threat hunters, especially malware hunters, often rely on reputation feeds or categorization to start an investigation. In their Enterprise Security product, Splunk has a great threat intelligence feeds feature that allows you to download and use all kinds of threat intel feeds to correlate data and increase detection capability.

When a domain/IP from a datamodel correlates with an IOC from these, they will appear in the “Threat Activity” section of Enterprise Security. Threat Activity is a datamodel by itself which means we can use it to build dashboards and reports and customize to achieve the results we want.

Here I will share some examples that analysts could find useful using feeds from Emerging Threats. I mostly use these queries to quickly see if there is anything relevant to investigate.

This query is using the Threat_Activity datamodel combined with the ET app macro to show all firewall connections to an IP categorized as CnC.

| tstats latest(_time) as _time,values(Threat_Activity.orig_sourcetype) as sourcetype,values(Threat_Activity.src) as src,values(Threat_Activity.dest) as dest, values(Threat_Activity.dest_port) as dest_port from datamodel=Threat_Intelligence.Threat_Activity where * Threat_Activity.orig_sourcetype="<sourcetype_name_here>" Threat_Activity.src="10.*.*.*" Threat_Activity.threat_key=iprepdata by Threat_Activity.threat_collection,Threat_Activity.threat_match_field,Threat_Activity.threat_match_value,Threat_Activity.src,Threat_Activity.dest,Threat_Activity.threat_key | `drop_dm_object_name("Threat_Activity")` | `get_threat_attribution("threat_key")` | `per_panel_filter("ppf_threat_activity","threat_match_field,threat_match_value")` | rename ppf_filter as filter | stats count by _time,threat_match_value,src,dest,threat_key | sort - filter,_time | table _time,src,dest,threat_key | `et_ip_lookup(IP=dest)` | search rep_category_name="CnC" | fields - threat_key

First, what I did was taking an already built query from Enterprise Security and modified it to fit my needs. I first precise that I only want firewall activity by adding Threat_Activity.orig_sourcetype=”<sourcetype_name_here>” and only from the 10.0.0.0/8 subnet with Threat_Activity.src=”10.*.*.*” (I could have used the CIDR but it didn’t work for some reason). Then I precise the specific threat feed I wish to use to eliminate noise from the free ones by adding Threat_Activity.threat_key=iprepdata (which is the ET one). Finally, I use the macro from the ET app to limit the results to the CnC category using | `et_ip_lookup(IP=dest)` | search rep_category_name=”CnC”

This is what it looks like after:

Capture1

From there, some modifications can be done to have more accurate results if desired, which has showing results only if the destination port from the log and the one observed by the feed matches and a score equal to or above 67.

| tstats latest(_time) as _time,values(Threat_Activity.orig_sourcetype) as sourcetype,values(Threat_Activity.src) as src,values(Threat_Activity.dest) as dest, values(Threat_Activity.dest_port) as dest_port from datamodel=Threat_Intelligence.Threat_Activity where * Threat_Activity.orig_sourcetype="<sourcetype_name_here>" Threat_Activity.src="10.*.*.*" Threat_Activity.threat_key=iprepdata by Threat_Activity.threat_collection,Threat_Activity.threat_match_field,Threat_Activity.threat_match_value,Threat_Activity.src,Threat_Activity.dest,Threat_Activity.threat_key | `drop_dm_object_name("Threat_Activity")` | `get_threat_attribution("threat_key")` | `per_panel_filter("ppf_threat_activity","threat_match_field,threat_match_value")` | rename ppf_filter as filter | stats count by _time,threat_match_value,src,dest_port,dest,threat_key | sort - filter,_time | table _time,src,dest,dest_port,threat_key | `et_ip_lookup(IP=dest)` | search rep_category_name=CnC rep_score >= 67 | fields - threat_key rep_cat_description | where dest_port=ports

From there, if you have an IDS, I suggest adding matching results from an IDS alert for increased confidence as we all know that IP-based IOCs are often unreliable and results are hard to contextualize.

By the way, the same can be done with proxy logs:

| tstats latest(_time) as _time,values(Threat_Activity.orig_sourcetype) as sourcetype,values(Threat_Activity.src) as src,values(Threat_Activity.dest) as dest from datamodel=Threat_Intelligence.Threat_Activity where * Threat_Activity.orig_sourcetype="<sourcetype_name_here>" Threat_Activity.threat_key="domainrepdata" by Threat_Activity.threat_collection,Threat_Activity.threat_match_field,Threat_Activity.threat_match_value,Threat_Activity.src,Threat_Activity.dest,Threat_Activity.threat_key | `drop_dm_object_name("Threat_Activity")` | `get_threat_attribution("threat_key")` | `per_panel_filter("ppf_threat_activity","threat_match_field,threat_match_value")` | rename ppf_filter as filter | stats count by _time,src,dest,threat_key | sort - filter,_time | table _time,src,dest,threat_key | `et_domain_lookup(DOMAIN=dest)` | search threat_level=Malicious rep_category_name=CnC | fields - threat_key

 

Analyzing code injected in a remote process via CreateRemoteThread

This is a commonly used technique in advanced malwares. This is from recent Sality sample submitted to VirusTotal. This code injection method is from the packer and not the malware itself. I won’t dive deep into the actual malware but want to simply show this method to analyze the injected code.

  1. The packer allocates memory in the space of taskhost.exe, changes protection as PAGE_EXECUTE_READWRITE.1
  2. Then it writes code in the memory space recently allocated.2
  3. Finally, it creates a thread in taskhost.exe that will execute the code.3-e1499696046540.png

Now, there is code that will be executed by a new thread spawned in taskhost.exe, we need to do the following to analyze it:

  1. In the hex dump, go to the buffer address pushed before calling WriteProcessMemory  (0130D10B here).
  2. Change the CALL instruction for a JMP that will loop on endlessly by replacing the E8 instruction with EB FE.4
  3. Step over and execute the call to CreateRemoteThread.
  4. Open a new debugger instance attach to taskhost.exe.
  5. In the CPU window, go the the address previously allocated by WriteProcesMemory (either by using “Go to Expression, checking the latest thread created or using the Memory Map).
  6. Change the JMP back to a CALL by changing EB FE back to E8 00. 6-e1499696098280.png
  7. Set a break point then on the call, resume execution, step over and have fun.