Name: Win32:Agent-OLH [Trj]
Compiler/Obfescation: VC++ 6, No obfuscation
This lab is IDA Pro training, we will check the malware dll and answer some questions
Looks like the question is about `DllEntryPoint.
.text:1001516D ; BOOL __stdcall DllEntryPoint(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
.text:1001516D public DllEntryPoint
.text:1001516D DllEntryPoint proc near
.text:1001516D
.text:1001516D hinstDLL = dword ptr 8
.text:1001516D fdwReason = dword ptr 0Ch
.text:1001516D lpReserved = dword ptr 10h
.text:1001516D
.text:1001516D push ebp
DllMain() address is0x1001516D
,
The library WS2_32.dll
is imported here, we are lokking for WS2_32_52 (gethostbyname)
.idata:100163C4 ; Imports from WS2_32.dll
.idata:100163C4 ;
.idata:100163C4 extrn WS2_32_18:dword ; CODE XREF: sub_10001656+3D2↑p
.idata:100163C4 ; DATA XREF: sub_10001656+3D2↑r ...
.idata:100163C4 ; Import by ordinal 18
.idata:100163C8 extrn WS2_32_11:dword ; CODE XREF: sub_10001074+11E↑p
.idata:100163C8 ; sub_10001074+1BF↑p ...
.idata:100163C8 ; Import by ordinal 11
.idata:100163CC extrn WS2_32_52:dword ; CODE XREF: sub_10001074:loc_100011AF↑p
.idata:100163CC ; sub_10001074+1D3↑p ...
Address is: 100163CC
Cross ref for gethostbyname:
Direction Type Address Text
Up r sub_10001074:loc_100011AF call ds:WS2_32_52
Up p sub_10001074:loc_100011AF call ds:WS2_32_52
Up r sub_10001074+1D3 call ds:WS2_32_52
Up p sub_10001074+1D3 call ds:WS2_32_52
Up r sub_10001074+26B call ds:WS2_32_52
Up p sub_10001074+26B call ds:WS2_32_52
Up r sub_10001365:loc_100014A0 call ds:WS2_32_52
Up p sub_10001365:loc_100014A0 call ds:WS2_32_52
Up r sub_10001365+1D3 call ds:WS2_32_52
Up p sub_10001365+1D3 call ds:WS2_32_52
Up r sub_10001365+26B call ds:WS2_32_52
Up p sub_10001365+26B call ds:WS2_32_52
Up r sub_10001656+101 call ds:WS2_32_52
Up p sub_10001656+101 call ds:WS2_32_52
Up r sub_1000208F+3A1 call ds:WS2_32_52
Up p sub_1000208F+3A1 call ds:WS2_32_52
Up r sub_10002CCE+4F7 call ds:WS2_32_52
Up p sub_10002CCE+4F7 call ds:WS2_32_52
Total: 9 functions
text:10001722 loc_10001722: ; CODE XREF: sub_10001656+B6↑j
.text:10001722 mov eax, off_10019040 ; "[This is RDO]pics.praticalmalwareanalys"...
.text:10001727 push 10h ; Size
.text:10001729 add eax, 0Dh
.text:1000172C push offset asc_10093540 ; " "
.text:10001731 push eax ; Buf1
.text:10001732 call memcmp
The url is in data section:
.data:10019194 aThisIsRdoPicsP db '[This is RDO]pics.praticalmalwareanalysis.com',0
.data:10019194 ; DATA XREF: .data:off_10019040↑o
Url is: [This is RDO]pics.praticalmalwareanalysis.com
Checking the function:
.text:10001656 ; =============== S U B R O U T I N E =======================================
.text:10001656
.text:10001656
.text:10001656 ; DWORD __stdcall sub_10001656(LPVOID lpThreadParameter)
.text:10001656 sub_10001656 proc near ; DATA XREF: sub_1000D02E+C8↓o
.text:10001656
.text:10001656 var_675 = byte ptr -675h
.text:10001656 var_674 = dword ptr -674h
.text:10001656 hModule = dword ptr -670h
.text:10001656 var_66C = word ptr -66Ch
.text:10001656 var_668 = dword ptr -668h
.text:10001656 var_664 = word ptr -664h
.text:10001656 var_662 = word ptr -662h
.text:10001656 var_660 = dword ptr -660h
.text:10001656 var_654 = word ptr -654h
.text:10001656 var_650 = dword ptr -650h
.text:10001656 Str1 = byte ptr -644h
.text:10001656 var_640 = byte ptr -640h
.text:10001656 CommandLine = byte ptr -63Fh
.text:10001656 Str = byte ptr -63Dh
.text:10001656 var_638 = byte ptr -638h
.text:10001656 var_637 = byte ptr -637h
.text:10001656 var_544 = dword ptr -544h
.text:10001656 var_50C = dword ptr -50Ch
.text:10001656 var_500 = dword ptr -500h
.text:10001656 Buf2 = byte ptr -4FCh
.text:10001656 var_4BC = dword ptr -4BCh
.text:10001656 var_4B8 = dword ptr -4B8h
.text:10001656 hKey = HKEY__ ptr -3B8h
.text:10001656 var_3B0 = dword ptr -3B0h
.text:10001656 var_1A4 = dword ptr -1A4h
.text:10001656 var_194 = dword ptr -194h
.text:10001656 var_190 = byte ptr -190h
.text:10001656 lpThreadParameter= dword ptr 4
.text:10001656
.text:10001656 sub esp, 678h
.text:1000165C push ebx
.text:1000165D push ebp
If we will count only elements with prefix var_
- there are 21 variables, else 28 variables
[n.b] in my version of IDA Free it returns 28 vars and 0 args, in authors book it retuns 23 vards and 1 arg
If we will count all elements without prefix as argument - there are 7 arguments, else 0 arguments
After serach with strings screen I found:
xdoors_d:10095B20 ; char aCommandExeC[]
xdoors_d:10095B20 aCommandExeC db '\command.exe /c ',0 ; DATA XREF: sub_1000FF58:loc_100101D7↑o
xdoors_d:10095B31 align 4
xdoors_d:10095B34 aCmdExeC db '\cmd.exe /c ',0 ; DATA XREF: sub_1000FF58+278↑o
xdoors_d:10095B41 align 4
xdoors_d:10095B44 ; char aHiMasterDDDDDD[]
cmd.exe string addr is: 0x10095B34
It's used here:
.text:100101C2 call ds:GetSystemDirectoryA
.text:100101C8 cmp dword_1008E5C4, ebx
.text:100101CE jz short loc_100101D7
.text:100101D0 push offset aCmdExeC ; "\\cmd.exe /c "
.text:100101D5 jmp short loc_100101DC
It's used at: 0x100101D0
push offset aCmdExeC ; "\\cmd.exe /c "
.text:100101D5 jmp short loc_100101DC
.text:100101D7 ; ---------------------------------------------------------------------------
.text:100101D7
.text:100101D7 loc_100101D7: ; CODE XREF: sub_1000FF58+276↑j
.text:100101D7 push offset aCommandExeC ; "\\command.exe /c "
.text:100101DC
.text:100101DC loc_100101DC: ; CODE XREF: sub_1000FF58+27D↑j
.text:100101DC lea eax, [ebp+Destination]
.text:100101E2 push eax ; Destination
.text:100101E3 call strcat
It will call strcat() function from source to destination string. Most probably it will build a string like GetSystemDirectoryA() + \\cmd.exe /c
Original place of reference
.text:100101A2 mov eax, [ebp+hWritePipe]
.text:100101A5 push 400h ; uSize
.text:100101AA mov [ebp+StartupInfo.hStdError], eax
.text:100101AD mov [ebp+StartupInfo.hStdOutput], eax
.text:100101B0 lea eax, [ebp+Destination]
.text:100101B6 mov [ebp+StartupInfo.wShowWindow], bx
.text:100101BA push eax ; lpBuffer
.text:100101BB mov [ebp+StartupInfo.dwFlags], 101h
.text:100101C2 call ds:GetSystemDirectoryA
.text:100101C8 cmp dword_1008E5C4, ebx
List of references:
Direction Type Address Text
Up w sub_10001656+22 mov dword_1008E5C4, eax
Up r sub_10007312+E cmp dword_1008E5C4, edi
Up r sub_1000FF58+270 cmp dword_1008E5C4, ebx
App is setting this global at sub_10001656:
.text:10001656 sub_10001656 proc near ; DATA XREF: sub_1000D02E+C8↓o
....
.text:1000166B mov [esp+688h+var_674], ebx
.text:1000166F mov [esp+688h+hModule], ebx
.text:10001673 call sub_10003695
.text:10001678 mov dword_1008E5C4, eax
.text:1000167D call sub_100036C3
.text:10001682 push 3A98h ; dwMilliseconds
.text:10001687 mov dword_1008E5C8, eax
.text:1000168C call ds:Sleep
.text:10001692 call sub_100110FF
It happens at the address: 0x10001678
in sub_10001656
Target section:
.text:10010444 loc_10010444: ; CODE XREF: sub_1000FF58+4E0↑j
.text:10010444 push 9 ; Size
.text:10010446 lea eax, [ebp+Buf1]
.text:1001044C push offset aRobotwork ; "robotwork"
.text:10010451 push eax ; Buf1
.text:10010452 call memcmp
.text:10010457 add esp, 0Ch
.text:1001045A test eax, eax
.text:1001045C jnz short loc_10010468
.text:1001045E push [ebp+pExceptionObject]
.text:10010461 call sub_100052A2
.text:10010466 jmp short loc_100103F6
.text:10010468 ; -------------------------------------------
if strings are equal, it will cal the subroutine with registry manipulation
.text:100052A2 sub_100052A2 proc near ; CODE XREF: sub_1000FF58+509↓p
.text:100052A2
.text:100052A2 Buffer = byte ptr -60Ch
.text:100052A2 var_60B = byte ptr -60Bh
.text:100052A2 Data = byte ptr -20Ch
.text:100052A2 var_20B = byte ptr -20Bh
.text:100052A2 cbData = dword ptr -0Ch
.text:100052A2 Type = dword ptr -8
.text:100052A2 phkResult = dword ptr -4
.text:100052A2 arg_0 = dword ptr 8
.text:100052A2
.text:100052A2 push ebp
.text:100052A3 mov ebp, esp
.text:100052A5 sub esp, 60Ch
.text:100052AB and [ebp+Buffer], 0
.text:100052B2 push edi
.text:100052B3 mov ecx, 0FFh
.text:100052B8 xor eax, eax
.text:100052BA lea edi, [ebp+var_60B]
.text:100052C0 and [ebp+Data], 0
.text:100052C7 rep stosd
.text:100052C9 stosw
.text:100052CB stosb
.text:100052CC push 7Fh
.text:100052CE xor eax, eax
.text:100052D0 pop ecx
.text:100052D1 lea edi, [ebp+var_20B]
.text:100052D7 rep stosd
.text:100052D9 stosw
.text:100052DB stosb
.text:100052DC lea eax, [ebp+phkResult]
.text:100052DF push eax ; phkResult
.text:100052E0 push 0F003Fh ; samDesired
.text:100052E5 push 0 ; ulOptions
.text:100052E7 push offset aSoftwareMicros ; "SOFTWARE\\Microsoft\\Windows\\CurrentVe"...
.text:100052EC push 80000002h ; hKey
.text:100052F1 call ds:RegOpenKeyExA
.text:100052F7 test eax, eax
.text:100052F9 jz short loc_10005309
.text:100052FB push [ebp+phkResult] ; hKey
.text:100052FE call ds:RegCloseKey
.text:10005304 jmp loc_100053F6
and after that will jump to this location
.text:100106D3 loc_100106D3: ; CODE XREF: sub_1000FF58+3FA↑j
.text:100106D3 ; sub_1000FF58+477↑j ...
.text:100106D3 lea eax, [ebp+Buf1]
.text:100106D9 push eax ; Str
.text:100106DA call strlen
.text:100106DF test eax, eax
.text:100106E1 pop ecx
.text:100106E2 jz short loc_100106EA
.text:100106E4 call ds:GetTickCount
It will call GetTickCount() and some network activity after this section
Original location
.text:10007025 PSLIST proc near ; DATA XREF: .rdata:off_10017F78↓o
.text:10007025
.text:10007025 Str = dword ptr 0Ch
.text:10007025
.text:10007025 mov dword_1008E5BC, 1
.text:1000702F call sub_100036C3
.text:10007034 test eax, eax
.text:10007036 jz short loc_1000705B
.text:10007038 push [esp+Str] ; Str
.text:1000703C call strlen
.text:10007041 test eax, eax
.text:10007043 pop ecx
.text:10007044 jnz short loc_1000704E
.text:10007046 push eax
.text:10007047 call sub_10006518
.text:1000704C jmp short loc_1000705A
It will call sub_100036C3
which is checking version:
.text:100036C3 sub_100036C3 proc near ; CODE XREF: sub_10001656+27↑p
.text:100036C3 ; PSLIST+A↓p
.text:100036C3
.text:100036C3 VersionInformation= _OSVERSIONINFOA ptr -94h
.text:100036C3
.text:100036C3 push ebp
.text:100036C4 mov ebp, esp
.text:100036C6 sub esp, 94h
.text:100036CC lea eax, [ebp+VersionInformation]
.text:100036D2 mov [ebp+VersionInformation.dwOSVersionInfoSize], 94h
.text:100036DC push eax ; lpVersionInformation
.text:100036DD call ds:GetVersionExA
.text:100036E3 cmp [ebp+VersionInformation.dwPlatformId], 2
.text:100036EA jnz short loc_100036FA
.text:100036EC cmp [ebp+VersionInformation.dwMajorVersion], 5
.text:100036F3 jb short loc_100036FA
.text:100036F5 push 1
.text:100036F7 pop eax
.text:100036F8 leave
.text:100036F9 retn
If version is incorrect it will return from function, else it will do strlen() call with some checks. If all is ok it will call CreateToolhelp32Snapshot()
and then call GetModuleFileNameExA()
and then will do lopp with Process32Next()
- looks like it will collect a list of processes in the system
Original function is:
.text:10004E79 sub_10004E79 proc near ; CODE XREF: sub_1000FF58+4E5↓p
.text:10004E79
.text:10004E79 Buffer = byte ptr -400h
.text:10004E79 var_3FF = byte ptr -3FFh
.text:10004E79 arg_0 = dword ptr 8
.text:10004E79
.text:10004E79 push ebp
.text:10004E7A mov ebp, esp
.text:10004E7C sub esp, 400h
.text:10004E82 and [ebp+Buffer], 0
.text:10004E89 push edi
.text:10004E8A mov ecx, 0FFh
.text:10004E8F xor eax, eax
.text:10004E91 lea edi, [ebp+var_3FF]
.text:10004E97 rep stosd
.text:10004E99 stosw
.text:10004E9B stosb
.text:10004E9C call ds:GetSystemDefaultLangID
.text:10004EA2 movzx eax, ax
.text:10004EA5 push eax
.text:10004EA6 lea eax, [ebp+Buffer]
.text:10004EAC push offset aLanguageId0xX ; "\r\n\r\n[Language:] id:0x%x\r\n\r\n"
.text:10004EB1 push eax ; Buffer
.text:10004EB2 call ds:sprintf
.text:10004EB8 add esp, 0Ch
.text:10004EBB lea eax, [ebp+Buffer]
.text:10004EC1 push 0
.text:10004EC3 push eax ; Str
.text:10004EC4 call strlen
.text:10004EC9 pop ecx
.text:10004ECA push eax
.text:10004ECB lea eax, [ebp+Buffer]
.text:10004ED1 push eax
.text:10004ED2 push [ebp+arg_0]
.text:10004ED5 call sub_100038EE
.text:10004EDA add esp, 10h
.text:10004EDD pop edi
.text:10004EDE leave
.text:10004EDF retn
.text:10004EDF sub_10004E79 endp
It will call GetSystemDefaultLangID()
and do a sprintf(with pattern [Language: ] id %d
) and then will call sub function sub_100038EE
with some kind of network activity. It looks like set_language_header
or get_language_id
If we are talking about DllEntryPoint
- 0 calls, because it's dll
Original section:
.text:10001341 mov eax, off_10019020 ; "[This is CTI]30"
.text:10001346 add eax, 0Dh
.text:10001349 push eax ; String
.text:1000134A call ds:atoi
.text:10001350 imul eax, 3E8h
.text:10001356 pop ecx
.text:10001357 push eax ; dwMilliseconds
.text:10001358 call ds:Sleep
It will take string [This is CTI]30
shift by 13 elements (0Dh) we will have 30, then it will call atoi("30") -> 30 (int) and then will multiply on 1000 (3E8h) -> it will sleep 30000 milliseconds -> 30 seconds
Original location:
.text:100016FB loc_100016FB: ; CODE XREF: sub_10001656+374↓j
.text:100016FB ; sub_10001656+A09↓j
.text:100016FB push 6
.text:100016FD push 1
.text:100016FF push 2
.text:10001701 call ds:WS2_32_23
.text:10001707 mov edi, eax
.text:10001709 cmp edi, 0FFFFFFFFh
.text:1000170C jnz short loc_10001722
.text:1000170E call ds:WS2_32_111
.text:10001714 push eax
.text:10001715 push offset aSocketGetlaste ; "socket() GetLastError reports %d\n"
.text:1000171A call ds:__imp_printf
.text:10001720 pop ecx
.text:10001721 pop ecx
it will push 3 params for socket() - 6, 1, 2.
According to socket() definition in windows sockets library:
SOCKET WSAAPI socket(
[in] int af,
[in] int type,
[in] int protocol
);
Because we are pushing to the stack - we have to parse it like this:
af = 2 # AF_INET
type = 1 # SOCK_STREAM
protocol = 6# IPPROTO_TCP
Accodring to ASM reference
IN Input from port
(1) AL = port[imm]; (2) AL = port[DX]; (3) AX = port[imm]; (4) AX = port[DX];
Opcodes: 0xE4, 0xE5, 0xEC, 0xED
This instruction transfers a byte/word or long from immediete port to the operand.
Looks like it will try to check input from port, it may not work in VM. I found it with "Search bytes". Target section:
.text:100061B9 mov [ebp+ms_exc.old_esp], esp
.text:100061BC mov [ebp+var_1C], 1
.text:100061C0 and [ebp+ms_exc.registration.TryLevel], 0
.text:100061C4 push edx
.text:100061C5 push ecx
.text:100061C6 push ebx
.text:100061C7 mov eax, 564D5868h
.text:100061CC mov ebx, 0
.text:100061D1 mov ecx, 0Ah
.text:100061D6 mov edx, 5658h
.text:100061DB in eax, dx
.text:100061DC cmp ebx, 564D5868h
.text:100061E2 setz [ebp+var_1C]
.text:100061E6 pop ebx
.text:100061E7 pop ecx
.text:100061E8 pop edx
.text:100061E9 jmp short loc_100061F6
This function is referenced in exported function ``:
.text:1000E892 public InstallSB
.text:1000E892 InstallSB proc near ; DATA XREF: .rdata:off_10017F78↓o
.text:1000E892
.text:1000E892 Format = dword ptr -8
.text:1000E892 arg_8 = dword ptr 0Ch
.text:1000E892
.text:1000E892 mov eax, off_10019034 ; "[This is DVM] "
.text:1000E897 push esi ; ArgList
.text:1000E898 mov esi, ds:atoi
.text:1000E89E add eax, 0Dh
.text:1000E8A1 push eax ; String
.text:1000E8A2 call esi ; atoi
.text:1000E8A4 test eax, eax
.text:1000E8A6 pop ecx
.text:1000E8A7 jz short loc_1000E8D9
.text:1000E8A9 call sub_10006119
.text:1000E8AE test al, al
.text:1000E8B0 jnz short loc_1000E8BB
.text:1000E8B2 call sub_10006196
.text:1000E8B7 test al, al
.text:1000E8B9 jz short loc_1000E8D9
.text:1000E8BB
.text:1000E8BB loc_1000E8BB: ; CODE XREF: InstallSB+1E↑j
.text:1000E8BB push offset byte_1008E5F0 ; Format
.text:1000E8C0 call sub_10003592
.text:1000E8C5 mov [esp+8+Format], offset aFoundVirtualMa ; "Found Virtual Machine,Install Cancel."
.text:1000E8CC call sub_10003592
.text:1000E8D1 pop ecx
.text:1000E8D2 call sub_10005567
.text:1000E8D7 jmp short loc_1000E8F4
- It checks from DVM and SSD
- There is a direct message
Found Virtual Machine,Install Cancel
This is a section of bytes in .data section. Looks like a shell-code
.data:1001D988 db 2Dh ; -
.data:1001D989 db 31h ; 1
.data:1001D98A db 3Ah ; :
.data:1001D98B db 3Ah ; :
.data:1001D98C db 27h ; '
.data:1001D98D db 75h ; u
.data:1001D98E db 3Ch ; <
.data:1001D98F db 26h ; &
.data:1001D990 db 75h ; u
.data:1001D991 db 21h ; !
.data:1001D992 db 3Dh ; =
.data:1001D993 db 3Ch ; <
.data:1001D994 db 26h ; &
.data:1001D995 db 75h ; u
.data:1001D996 db 37h ; 7
.data:1001D997 db 34h ; 4
.data:1001D998 db 36h ; 6
.data:1001D999 db 3Eh ; >
.data:1001D99A db 31h ; 1
.data:1001D99B db 3Ah ; :
.data:1001D99C db 3Ah ; :
.data:1001D99D db 27h ; '
.data:1001D99E db 79h ; y
.data:1001D99F db 75h ; u
.data:1001D9A0 db 26h ; &
.data:1001D9A1 db 21h ; !
.data:1001D9A2 db 27h ; '
.data:1001D9A3 db 3Ch ; <
.data:1001D9A4 db 3Bh ; ;
.data:1001D9A5 db 32h ; 2
.data:1001D9A6 db 75h ; u
.data:1001D9A7 db 31h ; 1
.data:1001D9A8 db 30h ; 0
.data:1001D9A9 db 36h ; 6
.data:1001D9AA db 3Ah ; :
.data:1001D9AB db 31h ; 1
.data:1001D9AC db 30h ; 0
.data:1001D9AD db 31h ; 1
.data:1001D9AE db 75h ; u
.data:1001D9AF db 33h ; 3
.data:1001D9B0 db 3Ah ; :
.data:1001D9B1 db 27h ; '
.data:1001D9B2 db 75h ; u
.data:1001D9B3 db 5
.data:1001D9B4 db 27h ; '
.data:1001D9B5 db 34h ; 4
.data:1001D9B6 db 36h ; 6
.data:1001D9B7 db 21h ; !
.data:1001D9B8 db 3Ch ; <
.data:1001D9B9 db 36h ; 6
.data:1001D9BA db 34h ; 4
.data:1001D9BB db 39h ; 9
.data:1001D9BC db 75h ; u
.data:1001D9BD db 18h
.data:1001D9BE db 34h ; 4
.data:1001D9BF db 39h ; 9
.data:1001D9C0 db 22h ; "
.data:1001D9C1 db 34h ; 4
.data:1001D9C2 db 27h ; '
.data:1001D9C3 db 30h ; 0
.data:1001D9C4 db 75h ; u
.data:1001D9C5 db 14h
.data:1001D9C6 db 3Bh ; ;
.data:1001D9C7 db 34h ; 4
.data:1001D9C8 db 39h ; 9
.data:1001D9C9 db 2Ch ; ,
.data:1001D9CA db 26h ; &
.data:1001D9CB db 3Ch ; <
.data:1001D9CC db 26h ; &
.data:1001D9CD db 75h ; u
.data:1001D9CE db 19h
.data:1001D9CF db 34h ; 4
.data:1001D9D0 db 37h ; 7
.data:1001D9D1 db 75h ; u
.data:1001D9D2 db 6Fh ; o
.data:1001D9D3 db 7Ch ; |
.data:1001D9D4 db 64h ; d
.data:1001D9D5 db 67h ; g
.data:1001D9D6 db 66h ; f
.data:1001D9D7 db 61h ; a
.data:1001D9D8 db 0
.data:1001D9D9 db 0
.data:1001D9DA db 0
.data:1001D9DB db 0
IdaFree is not supporting python plugins. But i'm sure it will update the shellcode - and we will be able to see the asm instructions:
sea = ScreenEA()
for i in range(0x00,0x50):
b = Byte(sea+i)
decoded_byte = b ^ 0x55
PatchByte(sea+i,decoded_byte)
Here is the section in HEX-view:
00 00 00 00 00 00 00 00 2D 31 3A 3A 27 75 3C 26
75 21 3D 3C 26 75 37 34 36 3E 31 3A 3A 27 79 75
26 21 27 3C 3B 32 75 31 30 36 3A 31 30 31 75 33
3A 27 75 05 27 34 36 21 3C 36 34 39 75 18 34 39
22 34 27 30 75 14 3B 34 39 2C 26 3C 26 75 19 34
37 75 6F 7C 64 67 66 61 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
In the python script we are doint xor operation with each byte (x XOR 0x55). Here are the results of manual decryption
s = "2D 31 3A 3A 27 75 3C 26 75 21 3D 3C 26 75 37 34 36 3E 31 3A 3A 27 79 75 26 21 27 3C 3B 32 75 31 30 36 3A 31 30 31 75 33 3A 27 75 05 27 34 36 21 3C 36 34 39 75 18 34 39 22 34 27 30 75 14 3B 34 39 2C 26 3C 26 75 19 34 37 75 6F 7C 64 67 66 61"
>>> elems = s.split()
>>> result = []
>>> for elem in elems:
... result.append(int('0x' + elem, 16))
>>> [x ^ 0x55 for x in result]
[120, 100, 111, 111, 114, 32, 105, 115, 32, 116, 104, 105, 115, 32, 98, 97, 99, 107, 100, 111, 111, 114, 44, 32, 115, 116, 114, 105, 110, 103, 32, 100, 101, 99, 111, 100, 101, 100, 32, 102, 111, 114, 32, 80, 114, 97, 99, 116, 105, 99, 97, 108, 32, 77, 97, 108, 119, 97, 114, 101, 32, 65, 110, 97, 108, 121, 115, 105, 115, 32, 76, 97, 98, 32, 58, 41, 49, 50, 51, 52]
It looks like ascii characters. Let's decode them:
>>> "".join([chr(x ^ 0x55) for x in result])
'xdoor is this backdoor, string decoded for Practical Malware Analysis Lab :)1234'
Result: this IDA plugin recodes this section into text xdoor is this backdoor, string decoded for Practical Malware Analysis Lab :)1234
19/21