how to access linker symbol in c code with MinGW? - gcc

I am using Mingw gcc and ld to generate an executable for windows.
I would like to access the start address of a section in c code, but I have tried a lot of methods and no one works.
My linker script file has this:
.data BLOCK(__section_alignment__) :
{
__data_start__ = . ;
*(.data)
*(.data2)
*(SORT(.data$*))
KEEP(*(.jcr))
__data_end__ = . ;
*(.data_cygwin_nocopy)
}
In C code I do this:
extern char __data_start__;
uint32_t test = &__data_start__;
And get this error:
undefined reference to __data_start__
Could anyone help me with this?
Thanks

mingw32 is using leading underscores, i.e. the compiler will add a _ (underscore) to each symbol. The part of the linker description file you are showing is part of the default linker script (at least in my installation), and for your code I am getting the mentioned error for
int main()
{
extern char __data_start__;
return (int) &__data_start__;
}
with -save-temps, the assembly code has
movl $___data_start__, %eax
which has 3 leading _'s not just 2.
Thus, there are 2 solutions: You can advise the compiler to emit __data_start__ as assembly name, which is a GCC extension:
int main()
{
extern char some_identifier __asm("__data_start__");
return (int) &some_identifier;
}
Or you can use _data_start:
int main()
{
extern char _data_start__;
return (int) &_data_start__;
}
Both use __data_start__ in assembly / object file:
movl $__data_start__, %eax
i686-w64-mingw32-nm module.o
U __data_start__

Related

gcc inline assembly: how to use intel syntax temporarily with constraint 'm' under 'gcc -masm=att' [duplicate]

This question already has answers here:
How to set gcc or clang to use Intel syntax permanently for inline asm() statements?
(2 answers)
Can I use Intel syntax of x86 assembly with GCC?
(2 answers)
Closed last year.
I'd like to use intel syntax gcc inline assembly, leaving gcc's default -masm=att dialect untouched.
The following code works fine:
#include <stdio.h>
int main(int argc, char *argv[])
{
int a = 123;
int b = 0;
printf("before: a = %d\n", a);
printf("before: b = %d\n", b);
__asm__ __volatile__ (
".intel_syntax noprefix\n\t"
"mov eax, %[a]\n\t"
"mov %[b], eax\n\t"
".att_syntax prefix\n\t"
: [b]"+r"(b)
: [a]"r"(a)
: "eax"
);
printf("after: a = %d\n", a);
printf("after: b = %d\n", b);
return 0;
}
// before: a = 123
// before: b = 0
// after: a = 123
// after: b = 123
But if i change Output Operands Constraint from register('r') to memory('m'), error occurs:
Error: junk `(%rbp)' after expression
In the generated assembly file, I find this:
#APP
.intel_syntax noprefix
mov eax, -16(%rbp)
mov -12(%rbp), eax
.att_syntax prefix
#NO_APP
It looks like gcc renders Assembler Template using AT&T Effective-Address dialect.
I searched the web, Extended Asm shows something like "Multiple assembler dialects in asm templates" and "x86 Operand Modifiers", but I still didn't solve the problem.
Is there a way to tell gcc, (maybe some instructions around __asm__, telling gcc to do operand-substitution with Intel-syntax addressing modes temporarily, like -masm=intel do in the whole file), render the Assembler Template using Intel Effective-Address dialect temporarily in __asm__ () block, not the whole file, like this:
#APP
.intel_syntax noprefix
mov eax, [%rbp - 16]
mov [%rbp - 12], eax
.att_syntax prefix
#NO_APP

Assembly program runs and immediately crashes without printing the Hello World message

Ok so basically I was just writing a C program to build my object files and then create executeables from them by using nasm and ld respectively
The program I wrote makes the correct calls to nasm and ld but I either compile fine with -f win32/win64 ( I'm on a 64 bit windows 7 machine ) or fail with the other options which is fine though... right? If the program compiles and creates the exe it runs and immediately crashes without printing the Hello World message. I'd Really like to jump into assembly. Some Help ?
section .text
global _start ;must be declared for linker (ld)
_start: ;tells linker entry point
mov edx,len ;message length
mov ecx,msg ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov ah,00
int 16h
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg db 'Hello, world!', 0xa ;our dear string
len equ $ - msg ;length of our dear string
I also happen to have a kali system ; I don't suppose I could compile for both operating systems without using Wine?
So my C program is working nicely! I can't find any examples of code to assemble though. Well I can... but it all fails. Does anyone have a link?
#include <stdio.h>
#include <stdlib.h>
#include <CustomHeader_Small.h>
void Assemble(void);
void PrintMenu(void);
void LoadOptions(void);
void SaveOptions(void);
char TempBuff[255];
char Format[30];
void SaveOptions(void)
{
FILE *Source = fopen("Settings.ini","w");
if(Source)
{
printf("%s","Enter A Format Type ->");
scanf("%s",Format); //Save Format
fprintf(Source,"Format:%s",Format);
fclose(Source);
puts("Settings Updated!");
LoadOptions();
}
return;
}
void LoadOptions(void)
{
FILE *Source = fopen("Settings.ini","r");
if(Source)
{
char ch;
int i;
char Line[50];
fscanf(Source,"%s",Line);
CCopy(Line,CPos(Line,":",0)+1,CLen(Line),Format,0,1);
free(Line);
}
else
{
Source = fopen("Settings.ini","w");
fprintf(Source,"%s","Format:Win32");
fclose(Source);
}
PrintMenu();
LoadOptions();
return;
}
void PrintMenu(void)
{
printf("%s","Menu:\n________\n1.) [C]reate A New Project.\n2.) [O]pen A Project.\n3.) [A]ssemble A Project.\n4.) [E]dit Settings\n");
printf("%s","5.) [Q]uit\n");
return;
}
void Assemble(void)
{
char *File=malloc(256);
printf("Note : Compiling In %s Mode\n",Format);
printf("%s","Enter A Project Name -> ");
scanf("%s",File);
char *Command;
int ch;
while((ch=getchar())!='S')
{
Command=malloc(1024);
strcpy(Command,"H:\\Users\\Grim\\AppData\\Local\\nasm\\nasm.exe -f ");
strcat(Command,Format);
strcat(Command," ");
strcat(Command,File);
strcat(Command,"\\");
strcat(Command,File);
strcat(Command,".asm ");
strcat(Command,"-o ");
strcat(Command,File);
strcat(Command,"\\");
strcat(Command,File);//This Creates The Object File Using Nasm ( Not Just Yet But Were Well On Our Way!
strcat(Command,".o");
system(Command); //Calls Nasm.
free(Command);
Command=malloc(1024);
strcpy(Command,"H:\\MinGW\\bin\\ld.exe ");
strcat(Command,File);
strcat(Command,"\\");
strcat(Command,File);
strcat(Command,".o ");
strcat(Command,"-o ");
strcat(Command,File);//This Creates The Executable File Using Nasm ( Not Just Yet But Were Well On Our Way!
strcat(Command,"\\");
strcat(Command,File);
strcat(Command,".exe");
system(Command); //Calls Nasm.
free(Command);
puts("Press Enter To Compile Again But Enter An [S] Followed By Enter To [S]top.");
}
free(File);
puts("NasmWrapper Assembly Done!");
printf("%s","\n\n\n");
PrintMenu();
return;
}
int main()
{
LoadOptions();
char ch;
while((ch = getchar())!='Q')
{
if(ch=='A') Assemble();
if(ch=='E') SaveOptions();
}
return 0;
}
Also any comments on the C program would be nice :D Thanks for explaining how to use the [Code] thing.
Your assembly program, apart from that odd int 16h* is specifically for Linux (32-bit Linux, to be more precise). int 0x80 is the way you invoke one of the Linux kernel system calls.
Windows doesn't do it this way. Instead you call the Windows API or the C standard library.
This OS-specific variation is one of the reasons it is good to use a higher level language rather than assembly.
If you want to play with assembly, my recommendation would be to decide on which OS you want to start with, and use that exclusively to begin with. Find some tutorials (there are lots for Linux and Windows) and get started. Once you have got it working for one OS, try it for another.
* int 16h calls the BIOS from DOS. This won't work in Linux.

GCC inline asm: how to use variable address as immediate operand in a shared lib?

The following code compiles into an executable with no problems:
static const char *foo = "bar";
void main(void)
{
__asm__ ("mov %0,%%rax"
:
: "i"(&foo)
: "%rax");
}
But as a shared lib, I get an error:
static const char *foo = "bar";
void zot(void)
{
__asm__ ("mov %0,%%rax"
:
: "i"(&foo)
: "%rax");
}
Compilation result:
hacker#lab$ gcc -shared -o mini-lib mini-lib.c
/usr/bin/ld: /tmp/ccwume3d.o: relocation R_X86_64_32S against `.data'
can not be used when making a shared object; recompile with -fPIC
/tmp/ccwume3d.o: error adding symbols: Bad value
Compiling with -fPIC makes no difference. How can I tweak this in such a way that the linker will relocate a reference to the address of foo? It needs to be an immediate integer operand in the asm.
Update: I ended up using a different instruction that takes a memory operand, since there is apparently no way to do this with immediate operands.
Would be good if you could clarify what exactly you're trying to achieve.
There is no 64bit movq $imm64, %reg, so you'd have to use movabs instead.
But there's also the X and P operand modifiers which might help by ditching the PLT reference / PC-relative addresses; you could write:
static void *foo;
[ ... ]
void *out[2];
asm("lea %P2, %0\n\t"
"movabs %X2, %1\n\t" : "=r"(out[0]), "=a"(out[1]) : "g"(foo));
So the question is, do you know (or want to explicitly specify) the exact address of foo ?
If so, this must be done via the linker (mapfiles or command line options to the linker, not the compiler).
Otherwise ... movabs, lea and/or the usage of P / X might do what you're looking for.

Bus error when calling Pause in OSX

section .text
global start
start:
mov eax, 29
int 80h
ret
I'm pretty sure that pause(void) is syscall 29, so why is this giving me Bus error: 10?
According to sys/syscall.h:
#define SYS_recvfrom 29
I would guess that recvfrom takes some other parameter, giving you the buss error.
If you are actually trying to call pause(void), a cursory examination of source seems to suggest that the definitions are something like the following:
syscalls.h:
#define SYS_sigsuspend 111
sigsuspend.c:
int
sigsuspend (
const sigset_t *sigmask_p
)
{
sigset_t mask;
if (sigmask_p)
mask = *sigmask_p;
else
sigemptyset(&mask);
return syscall (SYS_sigsuspend, mask);
}
sigcompat.c:
int sigpause(mask)
int mask;
{
return (sigsuspend((sigset_t *)&mask));
}
sigpause.c:
int
pause()
{
return sigpause(sigblock(0L));
}
So, while the pause(void) may not take any parameters, the syscall certainly does.
To call pause(void) from assembly, link with libc:
example.asm:
section .text
global start
start:
call pause
ret
Compile with as -o example.o example.asm and link with gcc -static -o a.out example.o

How to find the in-memory address of a specific instruction in a DLL

How can I find the in-memory address (for exploit writing) of a specific instruction?
Specifically, I'm looking for a call ebp instruction in user32.dll on Windows XP with no Service Pack whose address I can point EIP to. I have both Immunity Debugger and OllyDBG installed on the target.
To find an instruction, you need to figure out where the code, .text, section starts and ends, then load the DLL and just do liner search until you find the instruction.
Here we have a test DLL that has two call ebp instructions:
// test.c
// gcc -Wall -shared test.c -o test.dll
#include <stdio.h>
__declspec(dllexport) void test(void) {
asm("call *%ebp");
puts("test");
asm("call *%ebp");
}
Compile it and load the DLL in ollydbg and click CTRL+F and search for CALL EBP:
6BEC125A |. FFD5 CALL EBP
6BEC125C |. C70424 6430EC6> MOV DWORD PTR SS:[ESP],test.6BEC3064 ; |ASCII "test"
6BEC1263 |. E8 74060000 CALL <JMP.&msvcrt.puts> ; \puts
6BEC1268 |. FFD5 CALL EBP
you see the address of the first instruction is at 0x6bec125a the second at 0x6bec1268. The opcode of call ebp is 0xff 0xd5, remember this.
Now we need to find the boundaries of the code, you can use objdump with -h:
> objdump --headers test.dll
test.dll: file format pei-i386
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000984 6bec1000 6bec1000 00000600 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE, DATA
1 .data 00000008 6bec2000 6bec2000 00001000 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .rdata 0000011c 6bec3000 6bec3000 00001200 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
....
>
the code starts at VMA, virtual memory address, 0x6bec1000 and its size is 0x984, so it ends at 0x6bec1000 + 0x984 = 0x6bec1984 as :
0x6bec1000
....
what is between are the DLL instructions
....
0x6bec1984
I hope that was clear so far.
If we want to code our call ebp scanner, we need to do the flowing:
Read the PE information and get the executable section information, usually .text, to find its relative address and its virtual size.
Load the DLL using LoadLibrary, it will return the base address of the DLL.
The virtual address of the beginning of the code section is: DLL base address + code section virtualAddress and it ends at DLL base address + code section virtualAddress + VirtualSize.
Now we are ready to loop through the code and look for 0xff 0xd5, call ebp's opcode, simple liner search.
Here is a simple implementation:
// findopcode.c
// gcc -Wall findopcode.c -o findopcode
#include <windows.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv) {
const char opcode[] = {0xff, 0xd5}; // The opcode of `call ebp'
FILE *dllFile;
HMODULE dllHandle;
IMAGE_DOS_HEADER dosHeader;
IMAGE_NT_HEADERS NtHeaders;
IMAGE_SECTION_HEADER sectionHeader;
unsigned int i;
unsigned char *starAddr;
unsigned char *endAddr;
if( argc < 2 ) {
printf("usage: %s [DLL]\n", argv[0]);
return -1;
}
if( ( dllFile = fopen(argv[1], "rb") ) == NULL ) {
perror("[!] Error");
return -1;
}
// Read the basic PE headers
fread(&dosHeader, sizeof(dosHeader), 1, dllFile);
fseek(dllFile, dosHeader.e_lfanew, SEEK_SET);
fread(&NtHeaders, sizeof(NtHeaders), 1, dllFile);
// Search for the executable section, .text section.
for( i = 0 ; i < NtHeaders.FileHeader.NumberOfSections ; i++ ) {
fread(&sectionHeader, sizeof(sectionHeader), 1, dllFile);
// If we found a section that contains executable code,
// we found our code setion.
if( (sectionHeader.Characteristics & IMAGE_SCN_CNT_CODE) != 0 ) {
printf("[*] Code section: `%s'\n", sectionHeader.Name);
break;
}
}
fclose(dllFile);
// Load the DLL to get it's base address
if( (dllHandle = LoadLibraryA(argv[1])) == NULL ) {
printf("[!] Error: loading the DLL, 0x%.8x\n", (unsigned int) GetLastError());
return -1;
}
// The code start at : base address + code virtual address
starAddr = (unsigned char *) dllHandle + sectionHeader.VirtualAddress;
// It ends at : base address + code virtual address + virtual size
endAddr = (unsigned char *) starAddr + sectionHeader.Misc.VirtualSize;
printf("[*] Base address : 0x%.8x\n", (unsigned int) dllHandle);
printf("[*] Start address: 0x%.8x\n", (unsigned int) starAddr);
printf("[*] End address : 0x%.8x\n", (unsigned int) endAddr);
// Simple liner search, when ever we find `0xff 0xd5' we print that address
for( endAddr -= sizeof(opcode) ; starAddr < endAddr ; starAddr++ ) {
if( memcmp(&opcode, (void *) starAddr, sizeof(opcode)) == 0 ) {
printf("[*] Found `call ebp` at: 0x%.8x\n", (unsigned int) starAddr);
}
}
FreeLibrary(dllHandle);
return 0;
}
Compile it and test it with that DLL:
> gcc -Wall findopcode.c -o findopcode
> findopcode.exe test.dll
[*] Code section: `.text'
[*] Base address : 0x6bec0000
[*] Start address: 0x6bec1000
[*] End address : 0x6bec1984
[*] Found `call ebp` at: 0x6bec125a
[*] Found `call ebp` at: 0x6bec1268
>
It works pretty well, let's try user32.dll:
> findopcode.exe \Windows\System32\user32.dll
[*] Code section: `.text'
[*] Base address : 0x75680000
[*] Start address: 0x75681000
[*] End address : 0x756e86ef
[*] Found `call ebp` at: 0x756b49b5
>
I only found one call ebp at 0x756b49b5. Note, you way want to check if you have a read access before you read with memcmp using IsBadReadPtr:
if( IsBadReadPtr(starAddr, sizeof(opcode)) == 0 &&
memcmp(&opcode, (void *) starAddr, sizeof(opcode)) == 0 ) {
so the program won't fail if you hit some area with some weird access.
An alternative way is to use the msfpescan from the metasploit framework:
msfpescan -j ebp user32.dll

Resources