2009-06-08 3 views
7

문자 배열에서 읽는 프로그램이 있습니다. 비 ASCII 문자 인 16 진수 0x01020304와 같도록 메모리의 문자열 값이 필요합니다. 그래서 문제는 런타임시 비 ASCII 문자를 문자열 리터럴 변수로 전달하는 방법입니다.C/C++에서 문자열 리터럴에 비 ASCII 문자를 삽입하는 방법

+0

이것은 C 또는 C++ 질문이 아니며, 중요한 질문입니다. 당신은 당신의 특정한 터미널로 그것을하는 방법을 찾아야 할 것입니다. 0x03은 ​​종종 프로세스를 종료시키는 원인이되므로 문제가 될 수 있습니다. – Don

+0

@ Don : 제어 터미널에 넘겨주는 0x03은 ​​데이터 입력 방법에 따라 달라질 수 있지만 (키보드를 통해 값을 입력하는 것과 같음) 그렇지 않을 수도 있습니다. 질문은 OP가 입력을받을 것으로 예상되는 방식에 다소 모호합니다. –

답변

17

이스케이프 시퀀스를 사용하십시오. 문자를 올바른 순서로 넣었는지 확인하십시오.

"\x01\x02\x03\x04" 

편집 :. 당신은 단순히 기존의 char 배열에 순서를 넣어에 할당해야하는 경우

char s[4]; 

// ... later ... 
s[0] = 0x01; 
s[1] = 0x02; 
s[2] = 0x03; 
s[3] = 0x04; 
(int32_t *)s을 캐스팅하여 번호를 할당하지 마십시오

, char 배열 올바른 정렬을 갖고 있지 않습니다.

+1

내 프로그램에 값을 코딩하는 경우 작동하지만 런타임시 입력 할 수 있어야합니다. 질문이 구체적이지 않은 경우 미안합니다. –

+1

Ben, 그에 따라 질문을 업데이트하십시오. – avakar

2

글쎄, 문자열 리터럴이 필요합니까?

모두 매우 유사합니다

const char* blah = "test"; 
char blah[] = "test"; 
char blah[] = { 't','e','s','t',0 }; 

당신은 확실히 아주 쉽게 귀하의 요구에 대한 세 번째 양식을 사용할 수 있습니다.

3

아마도 C에서 가장 쉬운 방법은 16 진수 이스케이프 표기법 인 "\x01\x02\x03\x04"을 사용하는 것입니다. (은 x없이, 값은 요즘 거의 인기하거나 이해하지 않은, 8 진수입니다.) 또는

,

char x[] = {1, 2, 3, 4, 0}; 

가 (작업 널 종료가 초기화 할 때 포함되어야한다는 것을주의해야 이처럼).

+0

내 프로그램에 값을 코딩하면 작동하지만 런타임에 입력 할 수 있어야합니다. 질문이 구체적이지 않은 경우 미안합니다. –

+0

그럼, 당신의 질문은 무엇입니까? 프로그램에 입력하는 방법은 무엇입니까? (아마도 환경에 대해 더 자세히 설명해야 할 것입니다.) 프로그램에서 한 번 이동하는 방법은 무엇입니까? –

2

모든 비 ASCII 문자 인 16 진수 0x01020304와 같도록 메모리의 문자열 값이 필요합니다.

조심 4 contigious 바이트 시스템이 빅 엔디안 또는 리틀 엔디안 경우에 따라 달라집니다 메모리에 배치되는 방법. 32 비트 필드가 어떻게 작동하는지 신경 쓰면 문자열 리터럴에 물건을 넣는 것만으로는 효과가 없습니다. 예를 들어

:

avakar에서 알 수 있듯이 당신은 시도 할 수 :

char cString[5] = "\x01\x02\x03\x04"; 

을하거나 단지

cString[0] = 0x01; 
cString[1] = 0x02; 
... 

을하지만 당신은 이해하는 메모리의 실제 물리적 레이아웃을 기대한다면 :

// assuming unsigned int is 32 bits 
unsigned int* cStringAlias = rentirpret_cast<int*>(&cString[0]); 
std::cout << (*cStringAlias) 

을주의 깊게 살펴보면 가장 중요한 바이트가 0 번째 위치에 있는지 3 번째 위치에 있는지에 따라 출력이 달라집니다.

출력은

0x01020304 

이상

0x04030201 

에 대한 endianess을 읽을 수 있습니다.

1

소스를 UTF8로 저장하고 모든 문자열을 UTF-8로 처리하십시오 (또는 뭔가 StringFromUTF()를 사용하십시오).

유니버설 코드 페이지에서 작업하지 않을 때마다 (예, UTF-8은 실제로 코드 페이지가 아닙니다 ...) 문제를 묻습니다.

0

당신은 std::hex를 사용하여 시도 할 수 있습니다 : 당신은 다음 예를 들어, 각 문자의 16 진수 값을 입력 할

int temp; 
char sentMessage[10]; 
     for(int i = 0; i < 10; ++i) 
     { 
      std::cin >> std::hex >> temp; 
      sentMessage[i] = temp; 
     } 

. 01 11 7F AA

0

콘솔의 유니 코드 지원에는 std::wcinstd::wcout을 사용할 수 있습니다. 그러나, 그들이 표준의 일부인지는 확실하지 않습니다. C 코드를 작성할 때

1

, 당신은 방어 적이기()를 사용할 수 이진 데이터 복사하기 : SRC이 문자열

memcpy(dest + offset, src, 4); 

경우, 당신은 아마도 올바른 순서를 얻을 수 있습니다. 이 정수 (예를 들어, uint32_t) 그리고 당신이 특정 엔디 언을해야하는 경우 방어 적이기()를 수행하기 전에 바이트의 순서를 반대로해야 할 수 있습니다 스왑()에 의해 정의된다

uint32_t src; 

... 

swap((unsigned char *) &src, 0, 3); 
swap((unsigned char *) &src, 1, 2); 

당신. 기계 endianness가 원하는 출력 endianness와 일치하지 않으면 만 수행해야합니다.

컴파일러 또는 C 라이브러리에서 설정 한 특정 정의를보고 endianness를 찾을 수 있습니다. 최소한 glibc (리눅스)에서, endian.h은 그러한 정의를 제공하고, byteswap.h은 또한 바이트 스와핑 기능을 제공합니다.

1

당신이 주입에 대해 이야기하고 있기 때문에, 나는 당신에게 단서를 줄 것입니다. (이는 학술적 목적으로 버퍼 오버 플로우 취약점을 악용하는 코드 삽입에 유용합니다 ...) 유니 코드를 수용하도록 터미널을 구성해야합니다 내 맥에서는 기본적으로 쓸 수있다).예를 들어 ∫ 같은 코드를 쓰면 유니 코드 문자를 입력 할 때 일반 문자처럼 메모리에서 한 바이트 만 가져 오지 않고 바이트 수가 더 많아집니다 (2 바이트, 3 바이트 또는 4 바이트가 될 수 있음). 어레이

char v[4]; 

및 메모리에있는 브이 (십진수)이 값으로 충전 될 필요이 ∫ 4 바이트

gets(v); //insecure function to read 

를 사용하여 입력하는 경우 :

-30 
-120 
-85 
0 

그 중 하나가 보이면 그 중 아무 것도 인쇄 할 수있는 ASCII 코드가 아닙니다. 메모리에 들어갈 수있는 코드 일 수도 있고 프로그램을 해킹하여 동일한 버퍼 오버 플로우를 이용하여 스택의 리턴 디렉토리를 변경하여 실행할 수도 있습니다 gets()를 허용하는 취약점. (코드가 HEX 편집기에서 프로그램을 열어 컴파일 된 모든 모습을 볼 수 있습니다)!

그래서 당신은 당신이 메모리가 스택에 할당하는 방법의 아이디어를 얻을 수있는이 링크 사람에서 파일

에 인쇄하여 필요에 맞게 올바른 유니 코드 문자를 찾을 수있다 http://eli.thegreenplace.net/2011/02/04/where-the-top-of-the-stack-is-on-x86/

(@Ben은 더 이상 계정이없는 것 같지만 안전한 프로그래밍을 배우는 사람이라면 누구나 사용할 수 있습니다.)

관련 문제