I can access the FS:[0h] which points to the SEH chain but cannot do the same for other segment registers.What is the reason for it ?

Also,I was debugging an exe which has PTRD at 0x600 and AEP at 0x1000 (same as PTRD) but at offset 0x400 I see some instructions which I have seen in some other files too. In my sample it is unreachable code,but in one test exe which I wrote using WINASM/MASM it was same sequence of instructions just had a bit more instruction .If I change the AEP to 400 the assembly is as follows:

00400400    6A 00           PUSH 0  
00400402    68 05304000     PUSH 00403005  
00400407    68 00304000     PUSH 00403000  
0040040C    6A 00           PUSH 0  
0040040E    E8 17040000     CALL 0040082A  
00400413    6A 00           PUSH 0  
00400415    E8 16040000     CALL 00400830  
0040041A    E8 17040000     CALL 00400836  
0040041F    E8 1E040000     CALL 00400842  
00400424    E8 13040000     CALL 0040083C  
00400429    C3              RETN     

I wrote a Hello world program in MASM which had AEP at 0x1000 the code seems similar but I can debug it i.e it is not unreachable/dead code like previous one.It is as follows:

00401000    6A 00           PUSH 0                                   
00401002    68 00304000     PUSH OFFSET 00403000                     
00401007    68 06304000     PUSH OFFSET 00403006                     
0040100C    6A 00           PUSH 0                                   
0040100E    E8 0D000000     CALL <JMP.&user32.MessageBoxA>           
00401013    A3 14304000     MOV DWORD PTR DS:[403014],EAX
00401018    33C0            XOR EAX,EAX
0040101A    50              PUSH EAX                                 
0040101B    E8 06000000     CALL <JMP.&kernel32.ExitProcess>         
00401020    FF25 08204000   JMP DWORD PTR DS:[<&user32.MessageBoxA>]
00401026    FF25 00204000   JMP DWORD PTR DS:[<&kernel32.ExitProcess 

So my question is how come code is coming in my sample at offset 0x400,what is the use of this code ,is there some compiler which is putting it out there?

Note:Its a virus sample and I am a starter.Thanks for the answers in advance...

2 Answers 2


In Windows, the total space the process is intended to see is the same in the CS, DS, and SS registers. Windows makes the executable file, as well as any DLLs, open files, allocated memory segments, etc. into this address range, and you'll see the same memory - and the same contents - no matter if you access cs:[something], ds:[something] or ss:[something]*.

On a 32 bit system, the reachable memory in this "big space" is 4 GB.

FS is different; it's a separate part of memory outside your normal address space. You can't access that memory using either of the normal registers. And its size is only a few bytes - you can't access FS:[100000h], for example, as the PEB isn't that big.

Back to the linear 4 GB space: the fact that 4 GB are "reachable" comes from 32 bit pointers (2^32); but it doesn't mean every address within that range is actually mapped to physical memory. Whenever windows needs a chunk of memory, it selects an address within that space, maps physical memory to it, and uses that memory. For example, when an executable gets loaded, windows will always** load it to 400000h . This is why your program starts at 401000h - your entry point of 1000h is relative to the load address, not to 0. Or, when windows loads a DLL, it will start with 80000000, adjust that value down to below other DLLs, randomize it a bit (for ASLR), and use that address. If your DLL has an entry point at 1000h, and gets loaded at 63000000h, execution will start at 63001000h.

The fact you can't access cs:[0] or ds:[0] is on purpose - windows doesn't map anything to the first bytes of the address space to make your program crash (technically: throw an execption) if it tries to access memory through a NULL pointer. This is, as well, the reason why executables get loaded higher in memory, you don't want a null pointer access to ever succeed accidentally.

The next thing to consider is how windows loads PE files - instead of parsing the file, and copying only the regions to memory that are actually used, it just slurps in the whole file to the start address***. Which means, the PE header gets loaded right to the load address. The pseudo code you've seen is just a part of the PE header that happens to be at offset 400h in your PE file.

To become familiar with memory layout of the "big" cs/ds/ss segment, i recommend the vmmap tool from the sysinternals collection; attach it to some running processes and check their memory map. The details will probably become much more clear from that than from any theoretical explanation.

(*) However, depending on access rights, you may not be allowed to write to those parts of this space that are mapped to code, or execute those parts that are mapped to data.

(**) for a somewhat fuzzy definition of always, the details aren't important right now

(***) Technically, it memory maps the file and relies on the paging subsystem to read it from disk, but again, this isn't important right now.

  • 1
    Actually, you can access the TEB using ds, you just need to know its linear address, which is stored in on one of the TEB fields (fs:18h IIRC). There is a separate TEB for each thread, so they may have different addresses, but they're all a part of the process' address space.
    – Igor Skochinsky
    Jul 7, 2015 at 13:04

executable code might start as low as base+0x2b0 if the linker switch /ALIGN:16 is used

enter image description here


the dead code could be a function that was compiled and linked but never called if you modufy the src above like this and compile the first call to messagebox will be available in the binary but no one will be referring it

#include <windows.h>
#pragma comment(lib , "user32.lib")
void deadcode(void)
  MessageBox(0,"iam dead","yep deady dead deady dead",0);
void main (void) {
  MessageBoxA(0,"disme to see me low",
  "using align 16 and merge sections iam slim(e)y",

this is the dead code that was never referenced but still exists

>cdb -c "x msgbox!*;q" msgbox.exe | grep main
004002d0 msgbox!main (void)

>cdb -c "u msgbox+2d0-20;q" msgbox.exe | grep -A 4 55
004002b0 55              push    ebp
004002b1 8bec            mov     ebp,esp
004002b3 6a00            push    0
004002b5 680c024000      push    offset msgbox!⌂USER32_NULL_THUNK_DATA+0x28 (004
004002ba 6828024000      push    offset msgbox!⌂USER32_NULL_THUNK_DATA+0x44 (004

>cdb -c "da msgbox+20c;q" msgbox.exe | grep dead
0040020c  "yep deady dead deady dead"
  • Thank you for the answer, I used cdb for the first time bcos of your mentioning it,but my question was not from where executable code can start but how dead code comes there ...
    – rebel87
    Jul 2, 2015 at 11:06
  • i edited my answer to add a plausible approach as to why what you refer to as dead code might be and why it might exist where you claim it exists
    – blabb
    Jul 3, 2015 at 4:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.