Shellcode analysis like a semi-PRO

During Nicolas Brulez‘s training at REcon there was a challenge where the goal was to have function names instead of hashes into IDA in order to make shellcode analysis easier. This post describes the problem with more detail, possible solutions and the approach I took to solve the challenge. If you would like to know the PRO version then take Nicolas’s training next year.

Introduction
In a few words, in order to resolve API function addresses, shellcode uses to parse EAT from loaded modules and compare a given function name with a hash, this is sometimes used by malware as well for the purpose of being stealth. More information about this technique is available here. The problem is that on IDA Pro you will have an output like the below:

seg000:00386C91                 mov     ecx, 0A1233BBCh
seg000:00386C96                 mov     edx, [ebp+4]
seg000:00386C99                 call    find_func_addr
seg000:00386C9E                 call    eax

Since there are many calls to find_func_addr, static analysis without knowing the function name related to each hash is very time-consuming, it would be necessary to follow each call on the debugger and manually update IDA Pro.

Possible solutions
There are two ways to solve this problem: statically or dynamically. Each of them has its advantages and disadvantages.

Dynamic
The only advantage I can think of this approach is that you don’t need to reverse engineer the hash function in order to get every function name, the disadvantages are: (a) the code can take different paths and then you won’t be able to identify all the hashes; (b) it’s not portable, the Immunity or Olly script needs to be changed for every other sample that use hashes. A similar example of using the dynamic approach can be found at the VRT blog.

Static
This is the approach I took, the advantages/disadvantages are the reserve of the dynamic one, I had to crack the hash algorithm (which was pretty simple) but at least the other parts can be easily portable for further samples.

The static solution
The solution is divided in three parts: (a) get the function names from EAT of a given DLL; (b) calculate the hash for each function name; (c) import the data into IDA.

Getting the function names
I ended up using DLL Export Viewer, Nicolas used pefile, I totally forgot about pefile. For the purpose of this post, the code below is enough to illustrate:

dll = "c:/windows/system32/kernel32.dll"
pe =  pefile.PE(dll)	
for func in pe.DIRECTORY_ENTRY_EXPORT.symbols:
    print func.name

Calculate the hash
This will change for every sample. On this example, the hash algorithm was very simple, it can get really complicated and then the dynamic approach would be better. There is a MUCH easier/clever way to calculate the hash, however, you will need to take Nicolas’s training to get to know it, his solution to this was a *facepalm* moment.

Hash function:

seg000:00386BE0 calc_hash       proc near               ; CODE XREF: find_func_addr+28p
seg000:00386BE0                 push    eax
seg000:00386BE1                 xor     eax, eax
seg000:00386BE3                 xor     ecx, ecx
seg000:00386BE5
seg000:00386BE5 loop_calc_hash:                         ; CODE XREF: calc_hash+13j
seg000:00386BE5                 lodsb
seg000:00386BE6                 test    al, al
seg000:00386BE8                 jz      short calc_hash_end
seg000:00386BEA                 xor     ecx, eax
seg000:00386BEC                 rol     ecx, 3
seg000:00386BEF                 inc     ecx
seg000:00386BF0                 shl     eax, 8
seg000:00386BF3                 jmp     short loop_calc_hash
seg000:00386BF5 ; ---------------------------------------------------------------------------
seg000:00386BF5
seg000:00386BF5 calc_hash_end:                          ; CODE XREF: calc_hash+8j
seg000:00386BF5                 pop     eax
seg000:00386BF6                 retn
seg000:00386BF6 calc_hash       endp

Relevant C code:

#include <stdio.h>
#include <inttypes.h>  
#include <string.h>

__inline__ rol(uint32_t operand, uint8_t width) { 
	__asm__ __volatile__ ("rol %%cl, %%eax" 
                          : "=a" (operand) 
                          : "a" (operand), "c" (width) 
                         );
}

int main(int argc, char* argv[]) {

	unsigned int i = 0;
	int out = 0;
	int eax = 0;
	FILE *ptr_file;
	char buf[100];

    ptr_file =fopen(argv[1],"r");
    if (!ptr_file) {
		printf("Unable to read text file\n");
		return 1;
	}
		while (fgets(buf,100, ptr_file)!=NULL) {
			for (i = 0; i < strlen(buf)-1; i++) {
				eax = eax | buf[i];
				out = out ^ eax;
				out = rol(out,3);
				out += 1;
				eax = eax << 8;
			}		
			printf("0x%08x",out);
			printf(",");
			printf("%s",buf);
			eax = 0;
			out = 0;
		}

	fclose(ptr_file);
	return 0;
}

Import data into IDA
Basically, the script below add Enums into IDA, later just press ‘M’ on every hash to get the function name. If the hash is not found, consider import other DLLs. I didn’t find any function in IDA to automatically “refresh” a hex value for an enum value, if this is available please let me know.

IDAPython script:

from idaapi import *
from idc import *

SANE_NAME_RE = re.compile("[@?$:`+&\[\]]", 0)

def sanitize_name(name):
    return SANE_NAME_RE.sub("_", name)

def main():
    enum_name = AskStr("Kernel32_Functions_Hash","Enter Enum name:")
    id = idc.AddEnum(0, enum_name, idaapi.hexflag())
    print 'Enum id %d' % (id)
    file_path = AskFile(0,"*.*","Open txt file")
    file = open(file_path,'r')
    addr = ''
    name = ''
    for line in file:        
        addr,name = line.split(',')
        addr_hex = long(addr,16) 
        name = sanitize_name(name).rstrip('\n')       

if __name__ == '__main__':
    main()

After executing script and adding the Enum to the hash value:

.data:00405159                 mov     ecx, KERNEL32_ExitProcess
.data:0040515E                 mov     edx, [ebp+4]
.data:00405161                 call    get_func_addr
.data:00405166                 push    0
.data:00405168                 call    eax

Conclusion
As shown on another post, even without a clean IAT or loading a binary file like when dealing with shellcodes, it’s still possible to have a decent static analysis by mixing IDAPython with other tools.

Cracking a simple DGA

On my last post, I described how I unpacked sample sha1 177449d28ca4e0dad76375fe05012edbb18b0439 which was part of a challenge proposed by Seculert which the goal was to write relevant algorithm with the same features as malware’s DGA.

On this post, I will describe the DGA implemented by the malware, show its output in IDA Pro and its relevant C code. Then, I will quickly describe some related work which could identify this kind of behavior. Finally, I will discuss this specific DGA effectiveness.

The DGA algorithm
This DGA is really weird, it only randomizes the first 4 bytes of the domain name, the remaining keeps being the same. The first domain is “cqipierihon.com” so the other domains will be something like “XXXXierihon.com”. The algorithm basically adds the value between the four bytes and for each subtract 0x1a until it is less than 0x1a and then add 0x61 in order to make sure it will remain between a-z.

IDA Output:

debug026:00886D1F DGA:
debug026:00886D1F                 push    ebp
debug026:00886D20                 mov     ebp, esp
debug026:00886D22                 push    edi
debug026:00886D23                 mov     edi, [ebp+8]
debug026:00886D26                 cmp     dword ptr [edi], 'ptth' ; EDI = ptr to domain
debug026:00886D2C                 jnz     short DGA_begin
debug026:00886D2E                 add     edi, 7
debug026:00886D31
debug026:00886D31 DGA_begin:                              ; CODE XREF: debug026:00886D2Cj
debug026:00886D31                 movzx   eax, byte ptr [edi]
debug026:00886D34                 movzx   ecx, byte ptr [edi+3]
debug026:00886D38                 add     eax, ecx
debug026:00886D3A                 push    eax
debug026:00886D3B                 call    decode
debug026:00886D40                 mov     [edi], al
debug026:00886D42                 movzx   eax, byte ptr [edi+1]
debug026:00886D46                 movzx   ecx, byte ptr [edi]
debug026:00886D49                 movzx   edx, byte ptr [edi+1]
debug026:00886D4D                 add     eax, ecx
debug026:00886D4F                 add     eax, edx
debug026:00886D51                 push    eax
debug026:00886D52                 call    decode
debug026:00886D57                 mov     [edi+1], al
debug026:00886D5A                 movzx   eax, byte ptr [edi+2]
debug026:00886D5E                 movzx   ecx, byte ptr [edi]
debug026:00886D61                 add     eax, ecx
debug026:00886D63                 dec     eax
debug026:00886D64                 push    eax
debug026:00886D65                 call    decode
debug026:00886D6A                 mov     [edi+2], al
debug026:00886D6D                 movzx   eax, byte ptr [edi+3]
debug026:00886D71                 movzx   ecx, byte ptr [edi+1]
debug026:00886D75                 movzx   edx, byte ptr [edi+2]
debug026:00886D79                 add     eax, ecx
debug026:00886D7B                 add     eax, edx
debug026:00886D7D                 push    eax
debug026:00886D7E                 call    decode
debug026:00886D83                 mov     [edi+3], al
debug026:00886D86                 pop     edi
debug026:00886D87                 leave
debug026:00886D88                 retn    4
debug026:00886D8B ; ---------------------------------------------------------------------------
debug026:00886D8B
debug026:00886D8B decode:                                 ; CODE XREF: debug026:00886D3Bp
debug026:00886D8B                                         ; debug026:00886D52p ...
debug026:00886D8B                 push    ebp
debug026:00886D8C                 mov     ebp, esp
debug026:00886D8E                 mov     eax, [ebp+8]
debug026:00886D91                 sub     eax, 61h
debug026:00886D94                 mov     ecx, 1Ah
debug026:00886D99
debug026:00886D99 decode_loop:                            ; CODE XREF: debug026:00886D9Fj
debug026:00886D99                 cmp     eax, ecx
debug026:00886D9B                 jb      short decode_end
debug026:00886D9D                 sub     eax, ecx
debug026:00886D9F                 jmp     short decode_loop
debug026:00886DA1 ; ---------------------------------------------------------------------------
debug026:00886DA1
debug026:00886DA1 decode_end:                             ; CODE XREF: debug026:00886D9Bj
debug026:00886DA1                 add     eax, 61h
debug026:00886DA4                 leave
debug026:00886DA5                 retn    4

DGA Crack
(if you’re an experience C programmer, forgive me :P, just don’t judge my strcpy() since it’s input is not controlled by the user)

#include "stdafx.h"
#include <string.h>
#include <stdlib.h>
#include <Windows.h>

char deobfuscate(unsigned int c) {
	unsigned int temp = 0;

	temp = c;
	temp -=  0x61;
	
	while (temp >= 0x1a)
		temp -= 0x1a;

	temp+= 0x61;
	return (unsigned char)temp;

}

char* dga(char* domain) {
	char *newdomain = (char *)calloc(strlen(domain)+1, sizeof(char));
	char* http = "http";
	unsigned int i = 0;
	unsigned int a = 0;
	unsigned int b = 0;
	unsigned int c = 0;

	strcpy(newdomain,domain); 
	
	while ((newdomain[i] == http[i]) && (i < 4))
		i++;									
	if (i == 4)
		newdomain = &newdomain[7]; 

	// I could have saved some variables below but I tried to do as close as possible to the assembly code from the DGA
	// most likely the attacker did not use code optimization or really used some inline assembly.
	// change domain: first byte
	a = *newdomain; // mov eax
	b = newdomain[3];
	b +=a ;
	c = deobfuscate(b);
	*newdomain = c;
	
	// change domain: second byte
	b = newdomain[1];
	a = newdomain[0];
	c = newdomain[1];
	a += b;
	a += c;
	c = deobfuscate(a);
	newdomain[1] = c;

	// change domain: third byte
	a = newdomain[2];
	b = newdomain[0];
	a+= b;
	a-= 1;
	c = deobfuscate(a);
	newdomain[2] = c;

	// change domain: fourth byte
	a = newdomain[3];
	b = newdomain[1];
	c = newdomain[2];
	a += b;
	a += c;
	c = deobfuscate(a);
	newdomain[3] = c;
	return newdomain;
}

int _tmain(int argc, _TCHAR* argv[])
{
	char *newdomain = (char *)calloc(23, sizeof(char));
	unsigned int i = 0;
	unsigned int MAX_COUNT = 20;

	strcpy(newdomain, "http://cqipierihon.com"); // fixed length, not an issue to use strcpy()
	printf("Current domain: %s\n", newdomain);
	
	// The DGA will change only the bytes 0-4 of the domain, it will be XXXXierihon.com, it will always have the same length
	// just change MAX_COUNT to have more domains
	for (; i < MAX_COUNT; i++) {
		newdomain = dga(newdomain);
		printf("New Domain: %s\n", newdomain);
	}

	system("pause");
	return 0;
}

First 10 domains

Current domain: http://cqipierihon.com
New Domain: kcknierihon.com
New Domain: qgsxierihon.com
New Domain: geqdierihon.com
New Domain: cwkvierihon.com
New Domain: qustierihon.com
New Domain: ccmtierihon.com
New Domain: oesbierihon.com
New Domain: icshierihon.com
New Domain: iysjierihon.com

Relevant research
Last year at H2HC, Stefano Zanero presented a research about identification of automatically generated domains. I believe this DGA could be easily detected by his tool. I found his slides at HITB archives here. UPDATE: Stefano Zanero provided me the link to the paper, it’s not free but is available here.

Conclusion
Even though this malware has a DGA, it’s really simple to crack (actually, it’s not necessary to crack a DGA to get its output) and predictable if compared with others like Zeus Gameover and Licat/Murofet. However, it might still be able to bypass some network security tools and help the attacker keeps operating the botnet if any takedown happens on the primary domain.

Restoring IAT with IDA Debugger and IDAPython

Introduction

Seculert kindly provided the security community with a challenge back in 2012 (which is not available anymore, ping me if you wish the sample), unfortunately I found this challenge only one or two months ago, the goal was to write relevant code which implements the malware’s DGA. This post does not describe the solution (I intend to post the solution in the near future) however it might help you take the first step in order to solve the challenge. The challenge was really fun and I would like to thank Seculert for making it available.

Basically, on this post I will describe how I managed to restore IAT after reaching OEP even though the new allocated code did not have a PE header at all, obviously that analysis could keep going without the reference (like on shellcode analysis) however it makes the life easier if IDA can identify that a given call is for a known Windows function. First, we will briefly describe how the packer stub works. Then, we will describe the problem which the packer stub poses to the analysis. Finally, we will look on how to solve the problem manually and later automating it using IDAPython.

The packer stub

In a few words, the trick on this sample is that it adds an exception handler, throws an exception and code execution is transferred to the exception handler, it changes the exception handler twice and the one which matters is basically at offset 0x46 from the new allocated memory through VirtualAlloc. The function which loads the DLLs checks if a software breakpoint is in place on every function comparing the first byte with 0xCC, so make sure you did not set any software breakpoint on the loaded APIs.

The problem

After reaching OEP at offset 0x1704 from file.exe (sha1sum 177449d28ca4e0dad76375fe05012edbb18b0439) even though I had the IAT references on Olly (as shown on Figure 1), when opening up the memory dump as a binary file on IDA (as shown on Figure 2) it does not recognize the function names like Olly. Also, since there was no DOS/PE header on the new allocated code, using tools such as ImpRec which helps restore IAT would be useless since IDA also wouldn’t be able to recognize the file as a PE. One solution would be to manually create the PE header but besides not being elegant it would be too much time consuming and not scalable. A possible solution which I did not implement is using Immunity Debugger in order to grab the value of each function along with its name and use MakeNameEx() in order to update them into IDA. The solution implemented is described below.

Figure 1 - Loaded function on OllyDBG

Figure 1 – Loaded function on OllyDBG

FIgure 2 - Code opened on IDA as a binary file

FIgure 2 – Code opened on IDA as a binary file

The solution (at least one of them)

Since the debugger is able to recognize the windows API (it loads them into memory through LoadLibrary/GetProcAddress) why not use IDA Debugger to do it and hopefully its integration with IDA analysis would solve the problem, this approach worked. Note that this same process is described using UPX as an example on the excellent book “The IDA Pro Book” by Chris Eagle (who kindly signed my book @ Defcon19).

After select the debugger (Debugger -> Select Debugger -> Local Win32 Debugger), put a breakpoint on 0x0040be18, let it run (F9), the value of EAX is the memory address which code execution will be transferred to, on this example 0x0088046, put another breakpoint on 0x0040be86 and let it run (F9), at this point the code has been de-obfuscated and copied into the new allocated memory prior to jumping into 0x00880046. The second step is to put a breakpoint on 0x00881704, jump into it and hit ‘C’ in order to transform data into code, put the software breakpoint and let it run (F9 – twice – let the exception handler executes), once breakpoint is reached we’ve got into the OEP within necessary libraries loaded into memory. However, IAT is still not fine, if you look at 0x008800cc (where IAT begins) the function name is not resolved correctly (as shown in Figure 3). The last step is to rename the function, however, prior to that is necessary to make the data as a DWORD instead of BYTE, in order to do that just run the following script commands:

start = 0x008800cc
end = 0x00880298
while (start <= end):
    MakeDword(start)
    start += 0x4

Then, select (IDC script uses SelStart() and SelEnd()) the beginning of IAT (0x008800cc) until the end (0x00880298) and execute the IDC script renimp.idc which will correctly rename the functions in order to “export” them into IDA analysis. The expected result is shown on Figure 4.

Finally, in order to “export” the IDA Debugger into IDA Analysis, View -> Open subviews -> Segments, select the debug register (on this example was debug026), edit the segment and select option “Loader Segment” (as shown on Figure 5), take the memory snapshot through Debugger -> Take memory snapshot -> Loader Segments, terminate the process (Ctrl+F2) and if you go to 0x008800cc you should see the re-constructed IAT.

Figure 3 - IAT not correctly resolved on IDA Debugger

Figure 3 – IAT not correctly resolved on IDA Debugger

Figure 4 - IAT after run renimp.idc

Figure 4 – IAT after run renimp.idc

Figure 5 - Change debug segment

Figure 5 – Change debug segment

Semi-Automating the solution

Even though the script below automate most of the process, some of them still need to be taken manually, there are also two scripts instead of one, this is the reason I call this a semi-automate solution. The big reason for that is that I didn’t find any conditional breakpoint where script code could be executed only after a determined breakpoint gets reached, perhaps a sleep into the script could work but that is not a good solution too, the real issue is the exception handler which stops execution while the script would keep getting executed.

First of all, select the Debugger (Debugger -> Select Debugger -> Local Win32 Debugger), run the first script S_challenge_seculert_rename_IAT1.py, let the exception handler execute and once breakpoint at offset 0x1704 is reached execute S_challenge_seculert_rename_IAT2.py and then follow the same steps above in order to save memory snapshot, go to View -> Open subviews -> Segments, select the debug register (on this example was debug026), edit the segment and select option “Loader Segment”, take memory snapshot through Debugger -> Take memory snapshot -> Loader Segments, stop the debugging and go back to IDA Pro analysis, consider forcing IDA to reanalyze the IDB through through Options -> Analysis -> Reanalyze program.

S_challenge_seculert_rename_IAT1.py:

addr = 0x40be0a
addr2 = 0x40be39
RunTo(addr)
GetDebuggerEvent(WFNE_SUSP, -1)
new_block = GetRegValue('eax')

new_ep = new_block + 0x46
RunTo(addr2)
GetDebuggerEvent(WFNE_SUSP, -1)
MakeCode(new_ep)
AddBpt(new_ep)

S_challenge_seculert_rename_IAT2.py:

new_block = ScreenEA() - 0x46
new_ep2 = new_block + 0x1704
RunTo(new_ep2)
GetDebuggerEvent(WFNE_SUSP, -1)

start = new_block + 0xcc
end = new_block + 0x298
while (start <= end):
	print 'entrou no while'
	MakeDword(start)
	start += 0x4
start = new_block + 0xcc
while start <= end:
	name = Name(Dword(start))
	idx = name.find("_")
	dllname = name[:idx]
	if dllname == 'ws2':
		idx = idx + 3
	funcname = name[idx+1:]
	if MakeNameEx(start, funcname, SN_CHECK|SN_NOWARN) == 0:
		print 'ERROR MakeNameEx for %s' % funcname
	start += 0x4

Both scripts are also available through Github.

Conclusion
Even though IDA Debugger might not be the debugger of choice of most of the Malware Analysts, its integration with IDA Pro might makes life easier sometimes and is totally worth looking into it if necessary to restore IAT in order to have a clean/better analysis of the binary.

Simple integer overflow

On [1] Listing 6-3 has one exploitable bug on OpenSSH 3.1, find snippet code below:

static void
input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
{
    u_int nresp;
    char **response = NULL, *method;

    nresp = packet_get_int();
    if (nresp > 0) {
        response = xmalloc(nresp * sizeof(char*));
        for (i = 0; i < nresp; i++)
            response[i] = packet_get_string(NULL);
    }   
    packet_check_eom();
}

Well, I didn’t want to compile openssh 3.1 so I created a simple code to illustrate the same problem, when run the program it crashed since the memory allocated is less than the one response is trying to access.

Here is the program which just print the output to illustrate this issue

#include <stdio.h>

int main(void)
{
	unsigned int nresp = 0x40000020;;
	unsigned int alloc;

	alloc = (nresp * sizeof(char *));

	printf("alloc = %08x\n", alloc);
	printf("nresp = %08x\n", nresp);

	return 0;

}

Output

./integer4 
alloc = 00000080
nresp = 40000020

Reference:
[1] TAOSSA

GDB Basics and Integer

I was studying integer overflow (or arithmetic overflow or any other name you might like) and took a look at a simple program in order to debug on GDB, I’m not a GDB user however I thought would be painful to boot a windows VM to use VS in order to attach my simple program into Olly then resolved to give GDB a chance. I’m just posting this so I can look at it later once forget GDB syntax.

The goal was basically to have a quick look at integer type storages, with malware I didn’t need to pay attention if the “variable” was an int, char or even if was signed or unsigned.

Here is the C code

#include <stdio.h>

int main(void) {

	int a = 10;
	unsigned int b = 0xFFFFFFFF;
	unsigned char c = 255;

	b += 1;
	c += 1;

	return 0;
}

Here is the GDB output

(gdb) set disassembly-flavor intel
(gdb) break main
Breakpoint 1 at 0x804839a: file integer1.c, line 5.
(gdb) run
Starting program: /root/integer/integer1

Breakpoint 1, main () at integer1.c:5
5		int a = 10;
(gdb) x/i $pc
0x804839a <main+6>:	mov    DWORD PTR [ebp-0x8],0xa
(gdb) disas main
Dump of assembler code for function main:
0x08048394 <main+0>:	push   ebp
0x08048395 <main+1>:	mov    ebp,esp
0x08048397 <main+3>:	sub    esp,0x10
0x0804839a <main+6>:	mov    DWORD PTR [ebp-0x8],0xa
0x080483a1 <main+13>:	mov    DWORD PTR [ebp-0xc],0xffffffff
0x080483a8 <main+20>:	mov    BYTE PTR [ebp-0x1],0xff
0x080483ac <main+24>:	add    DWORD PTR [ebp-0xc],0x1
0x080483b0 <main+28>:	add    BYTE PTR [ebp-0x1],0x1
0x080483b4 <main+32>:	mov    eax,0x0
0x080483b9 <main+37>:	leave
0x080483ba <main+38>:	ret
End of assembler dump.
(gdb) x/w 0xbffff708-8
0xbffff700:	0x080483d0
(gdb) step 1
6		unsigned int b = 0xFFFFFFFF;
(gdb) x/w 0xbffff708-8
0xbffff700:	0x0000000a
(gdb) x/i $pc
0x80483a1 <main+13>:	mov    DWORD PTR [ebp-0xc],0xffffffff
(gdb) x/w $ebp-0xc
0xbffff6fc:	0x00991ff4
(gdb) step 1
7		unsigned char c = 255;
(gdb) x/w $ebp-0xc
0xbffff6fc:	0xffffffff
(gdb) x/i $pc
0x80483a8 <main+20>:	mov    BYTE PTR [ebp-0x1],0xff
(gdb) x/w $ebp-0x1
0xbffff707:	0xfff78800
(gdb) step 1
9		b += 1;
(gdb) x/w $ebp-0x1
0xbffff707:	0xfff788ff
(gdb) x/b $ebp-0x1
0xbffff707:	0xff
(gdb) x/i $pc
0x80483ac <main+24>:	add    DWORD PTR [ebp-0xc],0x1
(gdb) x/w $ebp-0xc
0xbffff6fc:	0xffffffff
(gdb) step 1
10		c += 1;
(gdb) x/w $ebp-0xc
0xbffff6fc:	0x00000000
(gdb) x/i $pc
0x80483b0 <main+28>:	add    BYTE PTR [ebp-0x1],0x1
(gdb) x/b $ebp-1
0xbffff707:	0xff
(gdb) step 1
12		return 0;
(gdb) x/b $ebp-1
0xbffff707:	0x00
(gdb)

As observed on GDB, both variables b and c wraps into 0 since they are unsigned.

On this other example (code below) the integer variable can’t hold 0x100000040 than it “discard” the most significant bit and hold only 0x00000040, causing a “numeric overflow condition” [1].

#include <stdio.h>

int main(void)
{
	unsigned int a;
	a = 0xe0000020;
	a = a + 0x20000020;

	return 0;

}
(gdb) disas main
Dump of assembler code for function main:
0x08048394 <main+0>:	push   ebp
0x08048395 <main+1>:	mov    ebp,esp
0x08048397 <main+3>:	sub    esp,0x10
0x0804839a <main+6>:	mov    DWORD PTR [ebp-0x4],0xe0000020
0x080483a1 <main+13>:	add    DWORD PTR [ebp-0x4],0x20000020
0x080483a8 <main+20>:	mov    eax,0x0
0x080483ad <main+25>:	leave  
0x080483ae <main+26>:	ret    
End of assembler dump.
(gdb) x/i $ebp-4
0xbffff704:	add    BYTE PTR [eax],al
(gdb) x/r $ebp-4
0xbffff704:	add    BYTE PTR [eax],al
(gdb) x/w $ebp-4
0xbffff704:	0x00000000
(gdb) step 1
7		a = a + 0x20000020;
(gdb) x/w $ebp-4
0xbffff704:	0xe0000020
(gdb) step 1
9		return 0;
(gdb) x/w $ebp-4
0xbffff704:	0x00000040

Yet, another example from [1] the unsigned int variable “a” becomes 4,294,967,295 instead of -1 since it is unsigned causing a “numeric underflow condition”.

int main(void)
{
	unsigned int a;
	a=0;
	a=a-1;
	return 0;

}
(gdb) x/i $pc
0x804839a <main+6>:	mov    DWORD PTR [ebp-0x4],0x0
(gdb) x/w $ebp-4
0xbffff704:	0x00000000
(gdb) step 1
5		a=a-1;
(gdb) x/w $ebp-4
0xbffff704:	0x00000000
(gdb) step 1
6		return 0;
(gdb) x/w $ebp-4
0xbffff704:	0xffffffff
(gdb)

[1] TAOSSA

IDAPython to solve ELF crackme

Sergei Frankoff sent an e-mail to a mailing-list posting an available job on his team as an IT Security Analyst along with a challenge and guaranteed whoever solved the challenge would receive a phone call for interview. Even though I was not interested, I decided to look at the challenge and see if I could find the answer just for fun.
I really like this kind of approach, challenge potential candidates to let him/her know what is expected from him/her on a daily basis instead of going through tedious HR process and once candidate speak with the hiring manager realize the role was not what he/she expected. Fortunately, in information security, most of the technical jobs are discussed directly with the hiring manager.

The challenge is still available here, I would recommend you take the challenge instead of continue reading the post, it might not take more than 30-60 minutes from your day and might make your day even better.

I was lazy so I used GDB in order to solve the challenge. After that, I realised I didn’t know right way (without google) how to create a simple IDAPython script to solve the challenge. Then, I decided to write the script later and here it is.

The script is available through GitHub or just copy/paste text below:

def main():
	start = AskAddr(0x08048900,'Enter start address of string')
	end = start + (0x4*0x15)
	answer = []
	for ea in range(start, end):
		if Byte(ea) != 0x0:
			answer.append(chr(Byte(ea)-10)) # sub by 0xa
	print ''.join(answer[::-1])
	
if __name__ == '__main__':
	main()

Python autoindent on Vi

I always forget how to configure vi to properly work with Python so I will post what I use to do here so I can see it later and remember. Perhaps, it can be useful for others.

Since Python is an indent based language it is great to set autoindent:

:set autoindent

I also like to have it as a four spaces:

:set shiftwidth = 4

If you added a code block above or below and need to indent multiple lines, it is possible to use > and < such as:

:30,50 > # indent lines 30 until 50 one time

:30,50 >> # indent lines 30 until 50 twice

:30,50 < # decrease indent on lines 30 until 50 one time

Hopefully this is useful for someone else.



Follow

Get every new post delivered to your Inbox.