Use 'dd' to split the binary apart and extract the parts - linux-kernel

I have firmware file in .bin format, but need to obtain the romimage.img and Kernel uImage files required to reflash a bricked device.
I used Binwalk to identify different parts of a firmware binary, $ binwalk firmware.bin
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
392 0x188 uImage header, header size: 64 bytes, header CRC: 0xEF73A583, created: 1969-12-31 23:59:59, image size: 1572736 bytes, Data Address: 0x20008000, Entry Point: 0x20008000, data CRC: 0x3661C6EC, OS: Linux, CPU: ARM, image type: OS Kernel Image, compression type: none, image name: "SP2Xcybertan_rom_bin"
13596 0x351C gzip compressed data, maximum compression, from Unix, last modified: 2019-04-03 05:25:36
1573192 0x180148 uImage header, header size: 64 bytes, header CRC: 0x9053B22D, created: 1969-12-31 23:59:59, image size: 8474624 bytes, Data Address: 0x0, Entry Point: 0x0, data CRC: 0xFC8655E0, OS: Linux, CPU: ARM, image type: Filesystem Image, compression type: none, image name: "SP2Xcybertan_rom_bin"
1573256 0x180188 Squashfs filesystem, little endian, non-standard signature, version 3.1, size: 8473072 bytes, 1028 inodes, blocksize: 131072 bytes, created: 2019-04-03 05:36:06
from boot log:
Loading from NAND 32MiB 3,3V 8-bit, offset 0x80000
Image Name: SP2Xcybertan_rom_bin
Created: 1970-01-01 0:00:-1 UTC
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 1572736 Bytes = 1.5 MB
Load Address: 20008000
Entry Point: 20008000
... ... ... ...
Creating 11 MTD partitions on "gen_nand":
0x00000000-0x00060000 : "u-boot"
0x00060000-0x00080000 : "u-bootenv"
0x00080000-0x01460000 : "ROMIMAGE"
0x01460000-0x01b60000 : "HALFIMAGE"
0x00200000-0x01460000 : "LINUX_ROOTFS"
... ... ... ...
Now I need to split the firmware image apart and extract the Rom Image romimage.img and kernel uImage from firmware.bin: how to make this properly use linux dd command?

Related

SNMPGET works from program but not from CLI

I am working on an fax grabber, for a fax in our building only Samsung provides the software "Samsung Easy Printer Manager" the program sends an SNMPGET to the Printer as I saw in Wireshark
Frame 133: 89 bytes on wire (712 bits), 89 bytes captured (712 bits) on interface bridge102, id 5
Ethernet II, Src: Parallel_53:1e:29 (Mac), Dst: SamsungE_69:6f:fe (Mac)
Internet Protocol Version 4, Src: 192.168.178.125, Dst: 192.168.178.38
User Datagram Protocol, Src Port: 55160, Dst Port: 161
Simple Network Management Protocol
version: version-1 (0)
community: Test
data: get-request (0)
get-request
request-id: 10944
error-status: noError (0)
error-index: 0
variable-bindings: 1 item
1.3.6.1.4.1.236.11.5.11.81.12.16.1.2.1: Value (Null)
Object Name: 1.3.6.1.4.1.236.11.5.11.81.12.16.1.2.1 (iso.3.6.1.4.1.236.11.5.11.81.12.16.1.2.1)
Value (Null)
[Response To: 134]
[Time: 0.000019000 seconds]
Answer:
Frame 135: 93 bytes on wire (744 bits), 93 bytes captured (744 bits) on interface vmenet2, id 2
Ethernet II, Src: SamsungE_69:6f:fe (Mac), Dst: Parallel_53:1e:29 (Mac)
Internet Protocol Version 4, Src: 192.168.178.38, Dst: 192.168.178.125
User Datagram Protocol, Src Port: 161, Dst Port: 55160
Simple Network Management Protocol
version: version-1 (0)
community: Test
data: get-response (2)
get-response
request-id: 10944
error-status: noError (0)
error-index: 0
variable-bindings: 1 item
1.3.6.1.4.1.236.11.5.11.81.12.16.1.2.1: 01000000
Object Name: 1.3.6.1.4.1.236.11.5.11.81.12.16.1.2.1 (iso.3.6.1.4.1.236.11.5.11.81.12.16.1.2.1)
Value (OctetString): 01000000
[Response To: 134]
[Time: 0.012747000 seconds]
But if im sending the get Request from my Laptop I get:
SNMPv2-SMI::enterprises.236.11.5.11.81.12.16.1.2.1 = No Such Instance currently exists at this OID
and after i googled the OID there was no result.
Any Ideas

Inefficient memory usage when using object.get

I thought that when downloading s3 object into a file it would write to it by chunks to avoid loading the whole file into memory.
But apparently, this is not the case, this is my code:
puts("Memory (before file loaded): #{((`ps -o rss= -p #{Process.pid}`.to_i) / 1024.0).round(2)} MB")
my_s3_object.get(response_target: file_path)
puts("Memory (after file loaded): #{((`ps -o rss= -p #{Process.pid}`.to_i) / 1024.0).round(2)} MB")
Output:
Memory (before file loaded): 191.08 MB
Memory (after file loaded): 259.41 MB
Where my_s3_object is 130MB zip archive. Ok, so it's not fully loaded into memory but almost half of it.
Is there a way to improve memory usage by passing some params to get method? Or how do I do it?
I think you are looking for ranged requests, which are a "general" HTTP "pattern" and supported by the AWS SDK.
The documentation provides the following examples, which should allow you to download parts of the object, write them, discard the bytes from memory and read the next bytes until the whole file is downloaded. In the end memory usage will depend on the range of bytes you download with every request.
Example: To retrieve a byte range of an object
# The following example retrieves an object for an S3 bucket.
# The request specifies the range header to retrieve a specific
# byte range.
resp = client.get_object({
bucket: "examplebucket",
key: "SampleFile.txt",
range: "bytes=0-9",
})
resp.to_h outputs the following:
{
accept_ranges: "bytes",
content_length: 10,
content_range: "bytes 0-9/43",
content_type: "text/plain",
etag: "\"0d94420ffd0bc68cd3d152506b97a9cc\"",
last_modified: Time.parse("Thu, 09 Oct 2014 22:57:28 GMT"),
metadata: {
},
version_id: "null",
}
Streaming data to a block
# WARNING: yielding data to a block disables retries of networking errors
# However truncation of the body will be retried automatically using a range request
File.open('/path/to/file', 'wb') do |file|
s3.get_object(bucket: 'bucket-name', key: 'object-key') do |chunk, headers|
# headers['content-length']
file.write(chunk)
end
end

How can you decode output sequences from TFGPT2Model?

I'm trying to get generated text from the TFGPT2Model in the Transformers library. I can see the output tensor, but I'm not able to decode it. Is the tokenizer not compatible with the TF model for decoding?
Code is:
import tensorflow as tf
from transformers import (
TFGPT2Model,
GPT2Tokenizer,
GPT2Config,
)
model_name = "gpt2-medium"
config = GPT2Config.from_pretrained(model_name)
tokenizer = GPT2Tokenizer.from_pretrained(model_name)
model = TFGPT2Model.from_pretrained(model_name, config=config)
input_ids = tf.constant(tokenizer.encode("Hello, my dog is cute",
add_special_tokens=True))[None, :] # Batch size 1
outputs = model(input_ids)
print(outputs[0])
result = tokenizer.decode(outputs[0])
print(result)
The resulting output is:
$ python run_tf_gpt2.py
2020-04-16 23:43:11.753181: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libnvinfer.so.6
2020-04-16 23:43:11.777487: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libnvinfer_plugin.so.6
2020-04-16 23:43:27.617982: W tensorflow/python/util/util.cc:319] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
2020-04-16 23:43:27.693316: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcuda.so.1
2020-04-16 23:43:27.824075: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:981] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA n
ode, so returning NUMA node zero
...
...
2020-04-16 23:43:38.149860: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1241] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:1 with 10565 MB memory) -> physical GPU (device: 1, name: Tesla K80, pci bus id: 0000:25:00.0, compute capability: 3.7)
2020-04-16 23:43:38.150217: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:981] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2020-04-16 23:43:38.150913: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1241] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:2 with 10565 MB memory) -> physical GPU (device: 2, name: Tesla K80, pci bus id: 0000:26:00.0, compute capability: 3.7)
2020-04-16 23:43:44.438587: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcublas.so.10
tf.Tensor(
[[[ 0.671073 0.60760975 -0.10744217 ... -0.51132596 -0.3369941
0.23458953]
[ 0.6403012 0.00396247 0.7443729 ... 0.2058892 -0.43869907
0.2180479 ]
[ 0.5131284 -0.35192695 0.12285632 ... -0.30060387 -1.0279727
0.13515341]
[ 0.3083361 -0.05588413 1.0543617 ... -0.11589152 -1.0487361
0.05204075]
[ 0.70787597 -0.40516227 0.4160383 ... 0.44217822 -0.34975922
0.02535546]
[-0.03940453 -0.1243843 0.40204537 ... 0.04586177 -0.48230025
0.5768887 ]]], shape=(1, 6, 1024), dtype=float32)
Traceback (most recent call last):
File "run_tf_gpt2.py", line 19, in <module>
result = tokenizer.decode(outputs[0])
File "/home/.../transformers/src/transformers/tokenization_utils.py", line 1605, in decode
filtered_tokens = self.convert_ids_to_tokens(token_ids, skip_special_tokens=skip_special_tokens)
File "/home/.../transformers/src/transformers/tokenization_utils.py", line 1575, in convert_ids_to_tokens
index = int(index)
File "/home/.../venv/lib/python3.7/site-packages/tensorflow_core/python/framework/ops.py", line 853, in __int__
return int(self._numpy())
TypeError: only size-1 arrays can be converted to Python scalars
(I removed all the TF messages and modified paths of my environment)
Apparently, you are using the wrong GPT2-Model. I tried your example by using the GPT2LMHeadModel which is the same Transformer just with a language modeling head on top. It also returns prediction_scores. In addition to that, you need to use model.generate(input_ids) in order to get an output for decoding. By default, a greedy search is performed.
import tensorflow as tf
from transformers import (
TFGPT2LMHeadModel,
GPT2Tokenizer,
GPT2Config,
)
model_name = "gpt2-medium"
config = GPT2Config.from_pretrained(model_name)
tokenizer = GPT2Tokenizer.from_pretrained(model_name)
model = TFGPT2LMHeadModel.from_pretrained(model_name, config=config)
input_ids = tf.constant(tokenizer.encode("Hello, my dog is cute", add_special_tokens=True))[None, :] # Batch size 1
outputs = model.generate(input_ids=input_ids)
print(outputs[0])
result = tokenizer.decode(outputs[0])
print(result)

Linker Script Always Interprets Variables as Zero?

There are a lot of logs and other stuff below, so to skip to the punchline: I have a linker script and am setting variables within it, and using these variables to set up memory sections. But it seems like these variables are always being set to 0 no matter what I set them to in the script.
I am writing a linker script, trying to add two new memory sections to my output elf for an embedded systems application. I am trying to chop off the first bit of the preexisting RAM memory section, change the size of RAM accordingly, and place my new sections there.
Previously, using the nrf52840 development board and this library, I can modify the linker script for one of the example applications as so:
SEARCH_DIR(.)
GROUP(-lgcc -lc -lnosys)
__NewSection1Start = 0x20000000;
__TotalLength = 0x1000;
__NewSection2Length = __TotalLength / 2;
__NewSection1Length = __TotalLength / 2;
__NewSection2Start = __NewSection1Start + __NewSection1Length;
MEMORY
{
FLASH (rx) : ORIGIN = 0x0, LENGTH = 0xff000
NEWSECTION1 (rwx) : ORIGIN = __NewSection1Start, LENGTH = __NewSection1Length
NEWSECTION2 (rwx) : ORIGIN = __NewSection2Start, LENGTH = __NewSection2Length
RAM (rwx) : ORIGIN = 0x20000000 + __TotalLength, LENGTH = 0x40000
}
FLASH_PAGE_SIZE = 4096;
FLASH_DATA_PAGES_USED = 4;
SECTIONS
{
.newsection1 :
{
KEEP (*(.newsection1));
} > NEWSECTION1
.newsection2 :
{
KEEP (*(.newsection2));
} > NEWSECTION2
}
...
And this works perfectly. Recently, I have needed to port to the nrf9160 using the Zephyr RTOS, so I began using the NordicPlayground nrf library built on top of Zephyr at this link, modifying one of the sample apps in there. In trying to rewrite the program for that board and environment, using a technique similar to this, I did a similar thing with the Zephyr linker script, modifying it as before. The build process somehow takes what I have done and generates the file build/spm/zephyr/linker.cmd in the build output folder:
__TotalLength = 0x1000;
__NewSection1Start = 0x20000000;
__NewSection2Length = __TotalLength / 2;
__NewSection1Length = __TotalLength / 2;
__NewSection2Start = __NewSection1Start + __NewSection1Length;
MEMORY
{
FLASH (rx) : ORIGIN = 0x0, LENGTH = 0xc000
SRAM (wx) : ORIGIN = 0x20000000 + __TotalLength, LENGTH = (64 * 1K) - __TotalLength
NEWSECTION1 (rwx) : ORIGIN = __NewSection1Start, LENGTH = __NewSection1Length
NEWSECTION2 (rwx) : ORIGIN = __NewSection2Start, LENGTH = __NewSection2Length
IDT_LIST (wx) : ORIGIN = (0x20000000 + (64 * 1K)), LENGTH = 2K
}
ENTRY("__start")
SECTIONS
{
.newsection1 :
{
KEEP (*(.newsection1));
} > NEWSECTION1
.newsection2 :
{
KEEP (*(.newsection2));
} > NEWSECTION2
}
...
However, although I thought these two scripts should behave the same, trying to compile and link with the nrf9160 version with the Zephyr RTOS throws this error:
riley#riley-Blade:~<code_base>/nrf/samples/nrf9160/example_app$ west build -b nrf9160_pca10090ns
source directory: /home/riley<code_base>/nrf/samples/nrf9160/example_app
build directory: /home/riley<code_base>/nrf/samples/nrf9160/example_app/build
BOARD: nrf9160_pca10090ns (origin: CMakeCache.txt)
[6/17] Linking C executable spm/zephyr/spm_zephyr_prebuilt.elf
Memory region Used Size Region Size %age Used
FLASH: 32 KB 48 KB 66.67%
SRAM: 10000 B 60 KB 16.28%
NEWSECTION1: 0 GB 2 KB 0.00%
NEWSECTION2: 0 GB 2 KB 0.00%
IDT_LIST: 40 B 2 KB 1.95%
[12/17] Linking C executable zephyr/zephyr_prebuilt.elf
FAILED: zephyr/zephyr_prebuilt.elf
: && ccache /home/riley/gcc-arm-none-eabi-9-2019-q4-major/bin/arm-none-eabi-gcc zephyr/CMakeFiles/zephyr_prebuilt.dir/misc/empty_file.c.obj -o zephyr/zephyr_prebuilt.elf -Wl,-T zephyr/linker.cmd -Wl,-Map=/home/riley<code_base>/nrf/samples/nrf9160/example_app/build/zephyr/zephyr.map -u_OffsetAbsSyms -u_ConfigAbsSyms -Wl,--whole-archive app/libapp.a zephyr/libzephyr.a zephyr/arch/arm/core/libarch__arm__core.a zephyr/arch/arm/core/cortex_m/libarch__arm__core__cortex_m.a zephyr/arch/arm/core/cortex_m/mpu/libarch__arm__core__cortex_m__mpu.a zephyr/lib/libc/minimal/liblib__libc__minimal.a zephyr/subsys/net/libsubsys__net.a zephyr/subsys/net/ip/libsubsys__net__ip.a zephyr/drivers/gpio/libdrivers__gpio.a zephyr/drivers/serial/libdrivers__serial.a zephyr/modules/nrf/lib/bsdlib/lib..__nrf__lib__bsdlib.a zephyr/modules/nrf/lib/at_host/lib..__nrf__lib__at_host.a zephyr/modules/nrf/drivers/at_cmd/lib..__nrf__drivers__at_cmd.a /home/riley<code_base>/nrfxlib/bsdlib/lib/cortex-m33/hard-float/libbsd_nrf9160_xxaa.a -Wl,--no-whole-archive zephyr/kernel/libkernel.a zephyr/CMakeFiles/offsets.dir/arch/arm/core/offsets/offsets.c.obj -L"/home/riley/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/thumb/v8-m.main+fp/hard" -L/home/riley<code_base>/nrf/samples/nrf9160/example_app/build/zephyr -lgcc -Wl,--print-memory-usage /home/riley<code_base>/nrfxlib/crypto/nrf_oberon/lib/cortex-m33/hard-float/liboberon_3.0.0.a -lc -mthumb -mcpu=cortex-m33 -mfpu=fpv5-sp-d16 -Wl,--gc-sections -Wl,--build-id=none -Wl,--sort-common=descending -Wl,--sort-section=alignment -nostdlib -static -no-pie -Wl,-X -Wl,-N -Wl,--orphan-handling=warn -mabi=aapcs -march=armv8-m.main+dsp libspmsecureentries.a && :
Memory region Used Size Region Size %age Used
FLASH: 110428 B 976 KB 11.05%
SRAM: 24608 B 124 KB 19.38%
NEWSECTION1: 264 B 0 GB inf%
NEWSECTION2: 1 B 0 GB inf%
IDT_LIST: 120 B 2 KB 5.86/home/riley/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/bin/ld: zephyr/zephyr_prebuilt.elf section `.newsection1' will not fit in region `NEWSECTION1'
/home/riley/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/bin/ld: zephyr/zephyr_prebuilt.elf section `.newsection2' will not fit in region `NEWSECTION2'
/home/riley/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/bin/ld: section .newsection2 LMA [0000000000000000,0000000000000000] overlaps section .newsection1 LMA [0000000000000000,0000000000000107]
/home/riley/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/bin/ld: region `NEWSECTION1' overflowed by 264 bytes
/home/riley/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/bin/ld: region `NEWSECTION2' overflowed by 1 byte
collect2: error: ld returned 1 exit status
%
ninja: build stopped: subcommand failed.
ERROR: command exited with status 1: /home/riley/.local/bin/cmake --build /home/riley<code_base>/nrf/samples/nrf9160/example_app/build
This is really strange for me, because this ouptut makes it seem like NEWSECTION1 and NEWSECTION2 have 0 length and both start at address 0x0, but this definitely should not be the case looking at the used linker script. To further make this confusing, if I replace __NewSection1Length with 0x500, or something like that, then the memory section will be 0x500B long, meaning that it seems like the error is that using variables in this linker script are being ignored or set to 0? Any help would be very much appreciated.
Some of the more complicated features of Zephyr like bootloaders and SPM (secure partition manager) actually build using independent board definitions, linker scripts, and project configurations. Even though they all happen from one call to west build or ninja or make or whatever build tool you are configured with, they can sometimes end up mismatched.
You can see this if you go into the build output directory and notice that there will be multiple sub-directories with names like spm and mcuboot and zephyr. Each of these sub-directories will contain their own object files, map files, linker scripts, etc. The zephyr directory is the top level one that contains the build/link work for your final application and will merge in the pre-compiled binaries from the others. What I think is happening is that the prj.conf changes you made to create the custom sections in your application are only affecting one of these sub-builds. You likely need to find the prj.conf files for the other ones and modify them similarly.

!address command shows a different value for the User mode stack initial commit size

I read in Windows Internals that when a thread is created, by default 1 MB of virtual memory is reserved for the user stack. Out of this 1 MB, only the first page (0x1000) will be committed.
I can see this when i dump the image header using dumpbin.exe. Here is what dumpbin shows:
However when i dump the address space of this exe in Windbg using !address command, I see a difference. Windbg shows me that the initial committed size is equal to 3 pages i.e 0x3000
Does anyone know why there is a difference between the initial stack commit size that the image header and debugger shows?
That's a nice question and the key to the answer is understanding what the initial breakpoint is. How initial is it, for starters?
TLDR: The initial breakpoint it too late. That stack has already grown.
You haven't shared the binary you're dealing with, so I chose a binary that exhibits the same behaviour - cacls.exe on 64-bit Windows 10 (file version: 10.0.14393.0).
During the initial breakpoint we observe:
CommandLine: "c:\Windows\System32\cacls.exe"
Symbol search path is: srv*
Executable search path is:
ModLoad: 00007ff6`83bd0000 00007ff6`83bdc000 cacls.exe
ModLoad: 00007ff8`29ce0000 00007ff8`29eb1000 ntdll.dll
ModLoad: 00007ff8`27500000 00007ff8`275ab000 C:\Windows\System32\KERNEL32.DLL
ModLoad: 00007ff8`26f30000 00007ff8`2714d000 C:\Windows\System32\KERNELBASE.dll
ModLoad: 00007ff8`280b0000 00007ff8`2814e000 C:\Windows\System32\msvcrt.dll
ModLoad: 00007ff8`29b10000 00007ff8`29bb2000 C:\Windows\System32\advapi32.dll
ModLoad: 00007ff8`273d0000 00007ff8`27429000 C:\Windows\System32\sechost.dll
ModLoad: 00007ff8`254f0000 00007ff8`25522000 c:\Windows\System32\NTMARTA.dll
ModLoad: 00007ff8`27150000 00007ff8`27245000 C:\Windows\System32\ucrtbase.dll
ModLoad: 00007ff8`277c0000 00007ff8`278e1000 C:\Windows\System32\RPCRT4.dll
(1310.17b0): Break instruction exception - code 80000003 (first chance)
ntdll!LdrpDoDebuggerBreak+0x30:
00007ff8`29db34e0 cc int 3
0:000> !dh -f cacls
File Type: EXECUTABLE IMAGE
FILE HEADER VALUES
8664 machine (X64)
6 number of sections
57899A04 time date stamp Sat Jul 16 05:20:52 2016
0 file pointer to symbol table
0 number of symbols
F0 size of optional header
22 characteristics
Executable
App can handle >2gb addresses
OPTIONAL HEADER VALUES
20B magic #
14.00 linker version
4C00 size of code
3600 size of initialized data
0 size of uninitialized data
52F0 address of entry point
1000 base of code
----- new -----
00007ff683bd0000 image base
1000 section alignment
200 file alignment
3 subsystem (Windows CUI)
10.00 operating system version
10.00 image version
10.00 subsystem version
C000 size of image
400 size of headers
AF10 checksum
0000000000080000 size of stack reserve
0000000000002000 size of stack commit
0000000000100000 size of heap reserve
0000000000001000 size of heap commit
C160 DLL characteristics
High entropy VA supported
Dynamic base
NX compatible
Guard
Terminal server aware
0 [ 0] address [size] of Export Directory
7010 [ 1CC] address [size] of Import Directory
A000 [ 7F0] address [size] of Resource Directory
9000 [ 2DC] address [size] of Exception Directory
0 [ 0] address [size] of Security Directory
B000 [ 54] address [size] of Base Relocation Directory
6A10 [ 38] address [size] of Debug Directory
0 [ 0] address [size] of Description Directory
0 [ 0] address [size] of Special Directory
0 [ 0] address [size] of Thread Storage Directory
60E0 [ D0] address [size] of Load Configuration Directory
0 [ 0] address [size] of Bound Import Directory
61B0 [ 3B8] address [size] of Import Address Table Directory
0 [ 0] address [size] of Delay Import Directory
0 [ 0] address [size] of COR20 Header Directory
0 [ 0] address [size] of Reserved Directory
0:000> !address #rsp
Mapping file section regions...
Mapping module regions...
Mapping PEB regions...
Mapping TEB and stack regions...
Mapping heap regions...
Mapping page heap regions...
Mapping other regions...
Mapping stack trace database regions...
Mapping activation context regions...
Usage: Stack
Base Address: 00000049`8fbbc000
End Address: 00000049`8fbc0000
Region Size: 00000000`00004000 ( 16.000 kB)
State: 00001000 MEM_COMMIT
Protect: 00000004 PAGE_READWRITE
Type: 00020000 MEM_PRIVATE
Allocation Base: 00000049`8fb40000
Allocation Protect: 00000004 PAGE_READWRITE
More info: ~0k
Content source: 1 (target), length: 180
We see the initial stack commit size is 0x2000, but 0x4000 is actually committed.
But that's already very late during the process initialization process (no pun intended). All the import DLL are already loaded, for example.
The so-called "initial break-point" is simply a (more or less1) hardcoded int 3 instruction called by the process initializtion code in NTDLL. If you look at the stack at this point you'll see the aptly named LdrpDoDebuggerBreak function which is called by LdrpInitializeProcess:
0:000> k
# Child-SP RetAddr Call Site
00 00000049`8fbbee80 00007ff8`29d72e22 ntdll!LdrpDoDebuggerBreak+0x30
01 00000049`8fbbeec0 00007ff8`29da8986 ntdll!LdrpInitializeProcess+0x1962
02 00000049`8fbbf2c0 00007ff8`29d59fae ntdll!_LdrpInitialize+0x4e982
03 00000049`8fbbf340 00000000`00000000 ntdll!LdrInitializeThunk+0xe
By the time that happened the stack has already been used (for example, to load statically linked DLLs and perform their initialization code), so it shouldn't be much surprise that the stack has grown already.
To examine the process when it has just been created we need to break on the process creation event rather than on the initial breakpoint (which isn't that initial as we now understand).
We can do that either using sxe cpr and .restarting like I did or running WinDbg/NTSD with -xe cpr. Doing that reveals something interesting2:
0:000> .restart
CommandLine: C:\Windows\System32\cacls.exe
************* Symbol Path validation summary **************
Response Time (ms) Location
Deferred srv*
Symbol search path is: srv*
Executable search path is:
ModLoad: 00007ff6`83bd0000 00007ff6`83bdc000 cacls.exe
00007ff8`29d470b0 4883ec48 sub rsp,48h
0:000> .imgscan /l
MZ at 00007ff6`83bd0000, prot 00000002, type 01000000 - size c000
Name: cacls.exe
Loaded cacls.exe module
MZ at 00007ff8`29ce0000, prot 00000002, type 01000000 - size 1d1000
Name: ntdll.dll
Loaded ntdll.dll module
0:000> !address #rsp
Mapping file section regions...
Mapping module regions...
Mapping PEB regions...
Mapping TEB and stack regions...
Mapping heap regions...
Mapping page heap regions...
Mapping other regions...
Mapping stack trace database regions...
Mapping activation context regions...
Usage: Stack
Base Address: 0000004a`5428e000
End Address: 0000004a`54290000
Region Size: 00000000`00002000 ( 8.000 kB)
State: 00001000 MEM_COMMIT
Protect: 00000004 PAGE_READWRITE
Type: 00020000 MEM_PRIVATE
Allocation Base: 0000004a`54210000
Allocation Protect: 00000004 PAGE_READWRITE
More info: ~0k
Content source: 1 (target), length: 478
The committed region size is 0x2000 - like the header says!
If we let it continue we'll eventually get to the initial breakpoint with more stack comitted.
1I said more or less hardcoded because the actual code of the function is
0:000> uf ntdll!LdrpDoDebuggerBreak
ntdll!LdrpDoDebuggerBreak:
00007ff8`29db34b0 4883ec38 sub rsp,38h
00007ff8`29db34b4 488364242000 and qword ptr [rsp+20h],0
00007ff8`29db34ba 41b901000000 mov r9d,1
00007ff8`29db34c0 4c8d442440 lea r8,[rsp+40h]
00007ff8`29db34c5 418d5110 lea edx,[r9+10h]
00007ff8`29db34c9 48c7c1feffffff mov rcx,0FFFFFFFFFFFFFFFEh
00007ff8`29db34d0 e88b30fdff call ntdll!NtQueryInformationThread (00007ff8`29d86560)
00007ff8`29db34d5 85c0 test eax,eax
00007ff8`29db34d7 780a js ntdll!LdrpDoDebuggerBreak+0x33 (00007ff8`29db34e3) Branch
ntdll!LdrpDoDebuggerBreak+0x29:
00007ff8`29db34d9 807c244000 cmp byte ptr [rsp+40h],0
00007ff8`29db34de 7503 jne ntdll!LdrpDoDebuggerBreak+0x33 (00007ff8`29db34e3) Branch
ntdll!LdrpDoDebuggerBreak+0x30:
00007ff8`29db34e0 cc int 3
00007ff8`29db34e1 eb00 jmp ntdll!LdrpDoDebuggerBreak+0x33 (00007ff8`29db34e3) Branch
ntdll!LdrpDoDebuggerBreak+0x33:
00007ff8`29db34e3 4883c438 add rsp,38h
00007ff8`29db34e7 c3 ret
It does stuff like checking whether or not this thread is to be "hidden from the debugger", but basically it just breaks into the debugger.
2The .imgscan /l is needed because without it we get:
0:000> !address #rsp
No symbols for ntdll. Cannot continue.

Resources