there are API's that are required to write to a file
an example of documented apis used to open and write to a file are
file open -> kernel32.CreateFile
file write -> kernel32!WriteFile
these apis require kernelmode transition and it happens at
ntdll.NtCreateFile and ntdll!NtWriteFile
you can use ctrl+g in ollydbg to follow these apis and set a breakpoint there
assuming you have a file open an file write as in code below
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
void main(void) {
char *foo = "lets open a file and write in it something\n";
FILE *fp =NULL;
if((fp = fopen("c:\\somewrite.text" , "wb")) != NULL) {
fwrite(foo,strlen(foo),1,fp);
printf("we wrote this %s\n" , foo);
fclose(fp);
}
}
open the compiled exe in ollydbg v2.0
ctrl+g -> ntdll.NtCreateFile -> follow -> f2-> f9
you should break here
CPU Stack
Address Comments
ESP ==> ; /RETURN to KERNELBASE.CreateFileW+1D1
ESP+4 ; |Arg1 = 26F614
ESP+8 ; |Arg2 = 40100080
ESP+C ; |Arg3 = 26F5B8
ESP+10 ; |Arg4 = 26F5FC
ESP+14 ; |Arg5 = 0
ESP+18 ; |Arg6 = 80
ESP+1C ; |Arg7 = 3
ESP+20 ; |Arg8 = 5
ESP+24 ; |Arg9 = 60
ESP+28 ; |Arg10 = 0
ESP+2C ; \Arg11 = 0
ZwCreateFile is Documented as
NTSTATUS ZwCreateFile(
_Out_ PHANDLE FileHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
_In_opt_ PLARGE_INTEGER AllocationSize,
_In_ ULONG FileAttributes,
_In_ ULONG ShareAccess,
_In_ ULONG CreateDisposition,
_In_ ULONG CreateOptions,
_In_opt_ PVOID EaBuffer,
_In_ ULONG EaLength
);
the third argument is Pointer to _OBJECT_ATTRIBUTES which has a member ObjectName which is a pointer to _UNICODE_STRING
typedef struct _OBJECT_ATTRIBUTES {
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
so 0x26f5b8 is pointer to OBJECT_ATTRIBUTES
CPU Dump
Address Hex dump ASCII
0026F5B8 18 00 00 00|00 00 00 00|F4 F5 26 00|42 00 00 00| ôõ& B
0026F5C8 00 00 00 00|E0 F5 26 00| àõ&
the third member of this struct 0x0026f5f4 is a pointer to unicode string
CPU Dump
Address Hex dump ASCII
0026F5F4 2A 00 1A 02|88 99 40 00| * ˆ™@
the wide char buffer is 0x00409988
CPU Dump
Address Hex dump ASCII
00409988 5C 00 3F 00|3F 00 5C 00|63 00 3A 00|5C 00 73 00| \ ? ? \ c : \ s
00409998 6F 00 6D 00|65 00 77 00|72 00 69 00|74 00 65 00| o m e w r i t e
004099A8 2E 00 74 00|65 00 78 00|74 00 00 00| . t e x t
you can use follow in dump to follow and find the path
you can look at the call stack using ctrl+k
and locate function that may manipulate or create the paths prior to this
you can also use this shortcut for this specific function when you have broken on this API in dump window type ctrl+g and type in [[[esp+c]+8]+4]
deference third argument (esp+c) then deference the third member and then deference the second member