[] A \ A] A ^ A_ и; * 3 $ "в скомпилированном бинарном C - PullRequest
0 голосов
/ 18 октября 2019

Я на ноутбуке Ubuntu 18.04, кодирую C с VSCode и собираю его с помощью GNU gcc.

Я занимаюсь базовым проектированием своего собственного кода C и заметил несколько интересных деталей,из которых есть пара []A\A]A^A_ и ;*3$", которая, кажется, присутствует в каждом из моих скомпилированных двоичных файлов Си. Между ними обычно (или всегда) строки, которые я жестко кодирую для printf() функций.

Примером этого короткого фрагмента кода здесь является:

#include <stdio.h>
#include <stdbool.h>

int f(int i);

int main()
{
    int x = 5;
    int o = f(x);
    printf("The factorial of %d is: %d\n", x, o);
    return 0;
}

int f(int i)
{
    if(i == 0)
    {
        return i;
    }
    else
    {
        return i*f(i-1);
    }

}

... тогдаскомпилировано с использованием gcc test.c -o test.

Когда я запускаю strings test, выводится следующее:

/lib64/ld-linux-x86-64.so.2
0HSn(
libc.so.6
printf
__cxa_finalize
__libc_start_main
GLIBC_2.2.5
_ITM_deregisterTMCloneTable
__gmon_start__
_ITM_registerTMCloneTable
AWAVI
AUATL
[]A\A]A^A_
The factorial of %d is: %d
;*3$"
GCC: (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0
crtstuff.c
deregister_tm_clones
__do_global_dtors_aux
completed.7697
__do_global_dtors_aux_fini_array_entry
frame_dummy
__frame_dummy_init_array_entry
test.c
__FRAME_END__
__init_array_end
_DYNAMIC
__init_array_start
__GNU_EH_FRAME_HDR
_GLOBAL_OFFSET_TABLE_
__libc_csu_fini
_ITM_deregisterTMCloneTable
_edata
printf@@GLIBC_2.2.5
__libc_start_main@@GLIBC_2.2.5
__data_start
__gmon_start__
__dso_handle
_IO_stdin_used
__libc_csu_init
__bss_start
main
__TMC_END__
_ITM_registerTMCloneTable
__cxa_finalize@@GLIBC_2.2.5
.symtab
.strtab
.shstrtab
.interp
.note.ABI-tag
.note.gnu.build-id
.gnu.hash
.dynsym
.dynstr
.gnu.version
.gnu.version_r
.rela.dyn
.rela.plt
.init
.plt.got
.text
.fini
.rodata
.eh_frame_hdr
.eh_frame
.init_array
.fini_array
.dynamic
.data
.bss
.comment

То же, что и другие написанные мной скрипты, 2 куска []A\A]A^A_ и ;*3$" всегда всплывает, 1 до строк, используемых с printf, и один сразу после.

Мне любопытно: Что именно означают эти строки? Я предполагаю, что они в основном отмечают начало и конец использования жестко закодированных выходных строк.

Ответы [ 2 ]

1 голос
/ 18 октября 2019

Наши цифровые компьютеры работают с битами, чаще всего сгруппированными в байты, содержащие по 8 бит каждый. Значение такой комбинации зависит от контекста и интерпретации .

Неисчерпывающий список возможных интерпретаций:

  • ASCII-символы с восьмымбит игнорируется или принимается, только если 0;
  • 8-разрядное целое число со знаком или без знака;
  • код операции (или ее часть) одного конкретного машинного языка, каждый процессор (семейство) имеет свой собственныйдругой набор.

Например, шестнадцатеричное значение 0x43 можно увидеть как:

  1. ASCII-символ 'C';
  2. 8-разрядное целое число без знака67 (подписано - то же самое, если используется дополнение 2);
  3. Код операции "LD B, E" для ЦПУ Z80 (см. Я действительно стар и изучил этот процессор подробно);
  4. Код операции "EORS ari" для процессора ARM.

Теперь strings просто (не говоря уже "примитивно") просматривает данный файл и пытается интерпретировать байты как последовательности для печати ASCII-символы. По умолчанию последовательность должна содержать не менее 4 символов, а байты интерпретируются как 7-битный ASCII. Кстати, файл не обязательно должен быть исполняемым. Вы можете сканировать любой файл, но если вы предоставите ему объектный файл по умолчанию, он будет сканировать только те разделы, которые загружены в память.

Итак, вы видите последовательности байтов, которые случайно являются по крайней мере 4 печатными символами вряд. А поскольку некоторые шаблоны всегда находятся в исполняемом файле, это выглядит так, как будто они имеют особое значение. На самом деле они есть, но они не должны иметь отношение к строкам вашей программы.

Вы можете использовать strings, чтобы быстро заглянуть в файл, чтобы найти, ну, в общем, строки, которые могут помочь вам с чем угодновыполнить.

0 голосов
/ 18 октября 2019

То, что вы видите, представляет собой ASCII-представление определенного битового шаблона, который часто встречается в исполняемых программах, генерируемых этим конкретным компилятором. Шаблон может соответствовать определенной последовательности инструкций машинного языка, которые компилятор любит испускать. Или это может соответствовать определенной структуре данных, которую компилятор или компоновщик использует для маркировки различных других частей данных, хранящихся в исполняемом файле. для вашего C-кода и вашей конкретной версии вашего конкретного компилятора, именно то, чему соответствуют битовые комбинации []A\A]A^A_ и ;*3$"Но я больше не занимаюсь программированием на машинном языке, поэтому я не собираюсь пробовать, и ответы, вероятно, в конце концов не будут слишком интересными.

Но это напоминает мне омаленькая причуда, которую я заметил и могу объяснить. Предположим, вы написали очень простую программу

int i = 12345;

Если вы скомпилировали эту программу и запустили на ней strings, и если вы сказали ей искать строки длиной не более двух символов,вы, вероятно, увидите (среди множества других коротких, бессмысленных строк) строку

90

и этот битовый шаблон, фактически, будет соответствовать вашей переменной! Что с этим?

Что ж, 12345 в шестнадцатеричном формате это 0x3039, и большинство машин в наши дни имеют младший порядок, поэтому эти два байта в памяти хранятся в другом порядке как

39 30

и в ASCII 0x39 - это '9', а 0x30 - '0'.

И если вам это интересно, вы можете попробовать скомпилировать фрагмент программы

int i = 12345;

long int a = 1936287860;
long int b = 1629516649;
long int c = 1953719668;

long long int x = 48857072035144;
long long int y = 36715199885175;

и запустив на нем strings -2, и посмотрите, что еще у вас получится.

...